LINQ中的标准偏差

Ste*_*ven 76 linq standard-deviation

LINQ是否为聚合SQL函数STDDEV() (标准差)建模?

如果没有,那么计算它的最简单/最佳实践方法是什么?

例:

  SELECT test_id, AVERAGE(result) avg, STDDEV(result) std 
    FROM tests
GROUP BY test_id
Run Code Online (Sandbox Code Playgroud)

Dyn*_*ard 94

您可以自己进行扩展计算

public static class Extensions
{
    public static double StdDev(this IEnumerable<double> values)
    {
       double ret = 0;
       int count = values.Count();
       if (count  > 1)
       {
          //Compute the Average
          double avg = values.Average();

          //Perform the Sum of (value-avg)^2
          double sum = values.Sum(d => (d - avg) * (d - avg));

          //Put it all together
          ret = Math.Sqrt(sum / count);
       }
       return ret;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您有一个人口样本而不是整个人口,那么您应该使用ret = Math.Sqrt(sum / (count - 1));.

转换为Chris Bennett添加标准偏差到LINQ的扩展.

  • Math.pow(d-avg,2)?我跳过函数调用并使用(d-avg)*(d-avg) (3认同)
  • 我将测试"values.Count()> 1",因为如果它正好是1,那么当你计算返回值时,你会有一个除以零的错误. (2认同)
  • 行ret = Math.Sqrt((sum)/ values.Count() - 1); 在values.Count() - 1周围缺少括号,它应该是ret = Math.Sqrt(sum /(values.Count() - 1)); (2认同)
  • 这样做的缺点是对“IEnumerable&lt;T&gt;”参数进行两次评估,这是不鼓励的。 (2认同)
  • @Yevgeniy Rozhkov - 你为什么删除` - 1`?根据[this](http://www.excelfunctions.net/Excel-Stdev-S-Function.html),需要` - 1`. (2认同)

Dav*_*rke 58

Dynami的答案有效,但会通过数据进行多次传递以获得结果.这是一种计算样本标准差的单程方法:

public static double StdDev(this IEnumerable<double> values)
{
    // ref: http://warrenseen.com/blog/2006/03/13/how-to-calculate-standard-deviation/
    double mean = 0.0;
    double sum = 0.0;
    double stdDev = 0.0;
    int n = 0;
    foreach (double val in values)
    {
        n++;
        double delta = val - mean;
        mean += delta / n;
        sum += delta * (val - mean);
    }
    if (1 < n)
        stdDev = Math.Sqrt(sum / (n - 1));

    return stdDev;
}
Run Code Online (Sandbox Code Playgroud)

这是样本标准差,因为它除以n - 1.对于正常的标准偏差,您需要除以n.

这使用Welford的方法,与Average(x^2)-Average(x)^2方法相比具有更高的数值精度.

  • 你错过了n的定义.还应注意,将和除以(n-1)而不是n使得这成为样本标准偏差 (3认同)
  • 为了更谨慎地复制SQL方法,我改变了`这个IEnumerable <double?> values`和`val in values.Where(val => val!= null)`.另外,我会注意到这种方法(Welford方法)比上述方法更准确,更快速. (3认同)
  • 您可能不会多次迭代整个序列,但您的方法仍会两次调用 GetEnumerator(这可能会触发复杂的 SQL 查询)。为什么不跳过条件并在循环结束时检查 n? (2认同)
  • 我已经编辑了你的答案,清楚地表明你正在计算**样本标准差**,而不是正常的**标准偏差**. (2认同)

小智 30

这将David Clarke的答案转换为与其他聚合LINQ函数(如Average)相同形式的扩展.

用法是: var stdev = data.StdDev(o => o.number)

public static class Extensions
{
    public static double StdDev<T>(this IEnumerable<T> list, Func<T, double> values)
    {
        // ref: https://stackoverflow.com/questions/2253874/linq-equivalent-for-standard-deviation
        // ref: http://warrenseen.com/blog/2006/03/13/how-to-calculate-standard-deviation/ 
        var mean = 0.0;
        var sum = 0.0;
        var stdDev = 0.0;
        var n = 0;
        foreach (var value in list.Select(values))
        {
            n++;
            var delta = value - mean;
            mean += delta / n;
            sum += delta * (value - mean);
        }
        if (1 < n)
            stdDev = Math.Sqrt(sum / (n - 1));

        return stdDev; 

    }
} 
Run Code Online (Sandbox Code Playgroud)


Vit*_*tas 5

var stddev = Math.Sqrt(data.Average(z=>z*z)-Math.Pow(data.Average(),2));
Run Code Online (Sandbox Code Playgroud)