문제

LINQ가 집계 SQL 기능을 모델링합니다 STDDEV() (표준 편차)?

그렇지 않다면, 그것을 계산하는 가장 간단한 / 베스트릭트 방법은 무엇입니까?

예시:

  SELECT test_id, AVERAGE(result) avg, STDDEV(result) std 
    FROM tests
GROUP BY test_id
도움이 되었습니까?

해결책

당신은 당신의 자신의 확장을 계산할 수 있습니다

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;
    }
}

당신이있는 경우 견본 전체 인구가 아닌 인구의 경우 사용해야합니다. ret = Math.Sqrt(sum / (count - 1));.

연장으로 변환되었습니다 Chris Bennett의 LINQ에 표준 편차 추가.

다른 팁

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;
}

이것이 샘플 표준 편차 나누기 때문에 n - 1. 일반적인 표준 편차를 위해서는 n 대신에.

이것은 사용합니다 Welford의 방법 이에 비해 수치 정확도가 높습니다 Average(x^2)-Average(x)^2 방법.

이것은 변환됩니다 데이비드 클라크의 대답 평균과 같은 다른 집계 LINQ 기능과 동일한 형태를 따르는 확장으로.

사용법은 다음과 같습니다. 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; 

    }
} 
var stddev = Math.Sqrt(data.Average(z=>z*z)-Math.Pow(data.Average(),2));

지점 (및 C#> 6.0)으로 바로 Dynamis 답변이됩니다.

    public static double StdDev(this IEnumerable<double> values)
    {
        var count = values?.Count() ?? 0;
        if (count <= 1) return 0;

        var avg = values.Average();
        var sum = values.Sum(d => Math.Pow(d - avg, 2));

        return Math.Sqrt(sum / count);
    }
public static double StdDev(this IEnumerable<int> values, bool as_sample = false)
{
    var count = values.Count();
    if (count > 0) // check for divide by zero
    // Get the mean.
    double mean = values.Sum() / count;

    // Get the sum of the squares of the differences
    // between the values and the mean.
    var squares_query =
        from int value in values
        select (value - mean) * (value - mean);
    double sum_of_squares = squares_query.Sum();
    return Math.Sqrt(sum_of_squares / (count - (as_sample ? 1 : 0)))
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top