Écart-type de LINQ

est-ce que LINQ modélise la fonction agrégée de SQL STDDEV() (écart-type)?

dans la négative, Quelle est la façon la plus simple / la plus pratique de le calculer?

exemple:

  SELECT test_id, AVERAGE(result) avg, STDDEV(result) std 
    FROM tests
GROUP BY test_id
70
demandé sur Steven 2010-02-12 20:48:21

5 réponses

Vous pouvez faire votre propre extension de calcul

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

si vous avez un échantillon de la population plutôt que de l'ensemble de la population, vous devez utiliser ret = Math.Sqrt(sum / (count - 1)); .

Transformé en extension à partir de Ajout d'Écart-type de LINQ par Chris Bennett .

88
répondu Dynami Le Savard 2014-04-08 07:15:36

la réponse de Dynami fonctionne mais fait plusieurs passages à travers les données pour obtenir un résultat. Il s'agit d'une méthode à passage unique qui calcule l'écart type de l'échantillon :

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

c'est le exemple d'écart type puisqu'il divise par n - 1 . Pour l'écart-type normal, vous devez diviser par n à la place.

on utilise à Cette Welford de la méthode qui a une précision numérique plus élevée que celle de la méthode Average(x^2)-Average(x)^2 .

52
répondu David Clarke 2017-04-13 12:57:55

cela convertit la réponse de David Clarke en une extension qui suit la même forme que les autres fonctions agrégées de LINQ comme la moyenne.

utilisation serait: 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; 

    }
} 
26
répondu Will Mathies 2017-05-23 12:34:39
var stddev = Math.Sqrt(data.Average(z=>z*z)-Math.Pow(data.Average(),2));
2
répondu Vitas 2015-03-06 12:03:24
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)))
}
0
répondu duc14s 2017-05-10 03:59:44