在List中对象的属性上使用Math.NET统计函数的最佳方法

时间:2014-02-25 11:24:19

标签: c# list mathnet

我正在试图找出快速执行计算的最佳方法,并希望找出人们在这种情况下通常会采取什么样的方法。

我有一个对象列表,其中包含我想要计算的均值和标准差的属性。我认为使用this Math.NET库可能更容易/优化性能。

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

据推测,答案取决于某些事情,比如列表的大小?让我们说为了论证,该列表有50个元素。我的担忧纯粹是表现。

2 个答案:

答案 0 :(得分: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));

答案 1 :(得分: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);