通用列表的标准差?

Tom*_*ler 56 c# math statistics standard-deviation

我需要计算通用列表的标准偏差.我会尝试包含我的代码.它是一个包含数据的通用列表.数据主要是浮点数和整数.这是我的代码相对于它而没有深入细节:

namespace ValveTesterInterface
{
    public class ValveDataResults
    {
        private List<ValveData> m_ValveResults;

        public ValveDataResults()
        {
            if (m_ValveResults == null)
            {
                m_ValveResults = new List<ValveData>();
            }
        }

        public void AddValveData(ValveData valve)
        {
            m_ValveResults.Add(valve);
        }
Run Code Online (Sandbox Code Playgroud)

以下是需要计算标准偏差的函数:

        public float LatchStdev()
        {

            float sumOfSqrs = 0;
            float meanValue = 0;
            foreach (ValveData value in m_ValveResults)
            {
                meanValue += value.LatchTime;
            }
            meanValue = (meanValue / m_ValveResults.Count) * 0.02f;

            for (int i = 0; i <= m_ValveResults.Count; i++) 
            {   
                sumOfSqrs += Math.Pow((m_ValveResults - meanValue), 2);  
            }
            return Math.Sqrt(sumOfSqrs /(m_ValveResults.Count - 1));

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

忽略LatchStdev()函数中的内容,因为我确定它不对.这只是我对计算st dev的不良尝试.我知道如何处理双打列表,但不是通用数据列表列表.如果有人有这方面的经验,请帮助.

Jon*_*rks 149

如果您的总体设置为1,则上面的示例稍微不正确并且可能有零除错误.以下代码稍微简单并给出"总体标准偏差"结果.(http://en.wikipedia.org/wiki/Standard_deviation)

using System;
using System.Linq;
using System.Collections.Generic;

public static class Extend
{
    public static double StandardDeviation(this IEnumerable<double> values)
    {
        double avg = values.Average();
        return Math.Sqrt(values.Average(v=>Math.Pow(v-avg,2)));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是答案,它计算标准偏差,而不是 LBushkin 的答案,后者真正计算样本标准偏差 (4认同)
  • 返回 Math.Sqrt(values.Average(v=&gt; (v-avg) * (v-avg))); 在我的机器上快了 3.37 倍。Math.Pow() 比普通乘法慢得多。 (4认同)
  • 从数学上来说,这是正确的答案。但是,您绝对应该避免在生产中使用此代码:参数是 IEnumerable&lt;double&gt;,使用此代码,IEnumerable 将被调用两次。举一个很好的例子,如果在 EF 查询上调用此函数会怎样?最好的方法是检查这个 IEnumreable 是否可以转换为集合,如果不能,请先执行 .ToList() 。 (2认同)

LBu*_*kin 63

本文应该对您有所帮助.它创建了一个计算double值序列偏差的函数.您所要做的就是提供一系列适当的数据元素.

由此产生的功能是:

private double CalculateStdDev(IEnumerable<double> values)
{   
  double ret = 0;
  if (values.Count() > 0) 
  {      
     //Compute the Average      
     double avg = values.Average();
     //Perform the Sum of (value-avg)_2_2      
     double sum = values.Sum(d => Math.Pow(d - avg, 2));
     //Put it all together      
     ret = Math.Sqrt((sum) / (values.Count()-1));   
  }   
  return ret;
}
Run Code Online (Sandbox Code Playgroud)

这很容易适应任何泛型类型,只要我们为计算的值提供选择器.LINQ非常适用Select于此,函数允许您从自定义类型的通用列表中投影一系列数值,以计算标准差:

List<ValveData> list = ...
var result = list.Select( v => (double)v.SomeField )
                 .CalculateStdDev();
Run Code Online (Sandbox Code Playgroud)

  • `if(values.Count()> 0)`行应该检查> 1,因为你要除以`values.Count() - 1`. (11认同)
  • 请注意,此算法实现了样本标准偏差,而不是"普通"标准偏差. (10认同)
  • 为了获得更快的性能(在我的计算机上为3.37倍),请乘以项而不是使用Math.Pow:(d-avg)*(d-avg)而不是:Math.Pow(d-avg,2) (3认同)
  • @Tom Hangler,确保在文件顶部添加“使用System.Linq;”以包含LINQ函数库。这些包括`Average()`和`Select()` (2认同)
  • double sum = values.Sum(d =&gt; (d - avg) * (d - avg)); (2认同)

Yur*_*rik 19

尽管接受的答案似乎在数学上是正确的,但从编程角度看它是错误的 - 它列举了相同的序列4次.如果底层对象是列表或数组,但如果输入是过滤/聚合/ etc linq表达式,或者如果数据直接来自数据库或网络流,这可能会导致性能低得多.

我强烈建议不要重新发明轮子并使用一个更好的开源数学库Math.NET.我们一直在我们公司使用lib,并对性能非常满意.

PM>安装包MathNet.Numerics

var populationStdDev = new List<double>(1d, 2d, 3d, 4d, 5d).PopulationStandardDeviation();

var sampleStdDev = new List<double>(2d, 3d, 4d).StandardDeviation();
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参见http://numerics.mathdotnet.com/docs/DescriptiveStatistics.html.

最后,对于那些想要获得最快结果并牺牲一些精度的人,请阅读"一次通过"算法https://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods