1

我试图找出快速执行计算的最佳方法,并想了解人们在这种情况下通常会采用哪种方法。

我有一个对象列表,这些对象具有我想要计算的平均值和标准差的属性。我认为使用这个Math.NET 库可能会更容易/优化性能。

不幸的是,这些函数的输入参数是数组。编写自己的函数来计算均值和 STD 是我唯一的解决方案吗?我可以为使用 lambda 函数的列表编写某种扩展方法?或者我最好编写返回对象属性数组的函数并将它们与 Math.NET 一起使用。

大概答案取决于一些事情,比如列表的大小?为了论证的缘故,我们假设该列表有 50 个元素。我关心的是纯粹的性能。

4

2 回答 2

5

ArrayStatistics确实需要数组,因为它针对这种特殊情况进行了优化(这就是它被称为 ArrayStatistics 的原因)。同样,StreamingStatistics针对 IEnumerable 序列流进行了优化,无需将数据保存在内存中。与所有类型的输入一起工作的通用类是Statistics类。

您是否验证过在您的用例中仅使用 LINQ 和 StreamingStatistics 不够快?为仅包含 50 个条目的列表计算这些统计数据几乎是不可测量的,除非说你在一个循环中这样做了一百万次。

使用 Math.NET Numerics v3.0.0-alpha7 的示例,使用列表中的元组来模拟您的自定义类型:

using MathNet.Numerics.Statistics;

var data = new List<Tuple<string, double>>
{
    Tuple.Create("A", 1.0),
    Tuple.Create("B", 2.0),
    Tuple.Create("C", 1.5)
};

// using the normal extension methods within `Statistics`
var stdDev1 = data.Select(x => x.Item2).StandardDeviation();
var mean1 = data.Select(x => x.Item2).Mean();

// single pass variant (unfortunately there's no single pass MeanStdDev yet):
var meanVar2 = data.Select(x => x.Item2).MeanVariance();
var mean2 = meanVar2.Item1;
var stdDev2 = Math.Sqrt(meanVar2.Item2);

// directly using the `StreamingStatistics` class:
StreamingStatistics.MeanVariance(data.Select(x => x.Item2));
于 2014-02-25T16:56:57.773 回答
1

您可以使用的最简单的解决方案是放置Linq以便转换List数组

  List<SomeClass> list = ...

  GetMeanAndStdError(list.ToArray()); // <- Not that good performance

但是,如果您关心性能,您宁愿显式计算平均值和方差(编写您自己的函数):

  List<SomeClass> list = ...

  Double sumX = 0.0;
  Double sumXX = 0.0;

  foreach (var item in list) {
    Double x = item.SomeProperty;

    sumX += x;
    sumXX += x * x;
  }

  Double mean = sumX / list.Count;
  Double variance = (sumXX / list.Count - mean);
于 2014-02-25T11:54:17.477 回答