90 votes

Équivalent LINQ pour l'écart type

Est-ce que LINQ modélise la fonction d'agrégation SQL STDDEV() (écart type)?

Si non, quel est le moyen le plus simple / les meilleures pratiques de le calculer?

Exemple:

   SELECT test_id, AVERAGE(result) avg, STDDEV(result) std 
    FROM tests
GROUP BY test_id
 

108voto

Dynami Le Savard Points 3053

Vous pouvez faire votre propre extension en le calculant

 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 la population entière, vous devez utiliser ret = Math.Sqrt(sum / (count - 1)); .

Transformé en extension de Adding Standard Deviation to LINQ par Chris Bennett .

70voto

David Clarke Points 3165

Dynami la réponse de travaux, mais effectue plusieurs passages à travers les données pour obtenir un résultat. C'est un seul passage méthode qui calcule l' écart-type d'é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 l' écart-type d'échantillon , car il divise en n - 1. Pour l'écart-type vous avez besoin de diviser par n à la place.

Il utilise Welford de la méthode qui a le plus de précision numérique par rapport à l' Average(x^2)-Average(x)^2 méthode.

33voto

Will Mathies Points 141

Ceci 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 telles que Average.

L'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: http://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; 

    }
} 
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X