46 votes

Comment déterminer l'écart type (stddev) d'un ensemble de valeurs?

J'ai besoin de savoir si un nombre par rapport à un ensemble de nombres est en dehors de 1 stddev de la moyenne, etc.

104voto

Jaime Points 25540

Tandis que la somme des carrés de l'algorithme fonctionne bien la plupart du temps, il peut causer de graves ennuis si vous êtes aux prises avec de très grands nombres. En gros, vous pourriez finir avec un écart négatif...

De Plus, ne jamais, jamais, jamais, calculer a^2 comme pow(a,2), a * a est presque certainement plus rapide.

De loin la meilleure façon de calculer un écart-type est de Welford de la méthode. Mes C est très rouillé, mais il pourrait ressembler à quelque chose comme:

public static double StandardDeviation(List<double> valueList)
{
    double M = 0.0;
    double S = 0.0;
    int k = 1;
    foreach (double value in valueList) 
    {
        double tmpM = M;
        M += (value - tmpM) / k;
        S += (value - tmpM) * (value - M);
        k++;
    }
    return Math.Sqrt(S / (k-2));
}

Si vous avez l' ensemble de la population (par opposition à un échantillon de la population), puis utilisez return Math.Sqrt(S / (k-1));.

EDIT: j'ai mis à jour le code en fonction de Jason remarques...

EDIT: j'ai aussi mis à jour le code en fonction de Alex remarques...

5voto

AlexB Points 11

La réponse acceptée par Jaime est excellente, sauf que vous devez diviser par k-2 à la dernière ligne (vous devez diviser par "number_of_elements-1"). Mieux encore, commencez k à 0:

 public static double StandardDeviation(List<double> valueList)
{
    double M = 0.0;
    double S = 0.0;
    int k = 0;
    foreach (double value in valueList) 
    {
        k++;
        double tmpM = M;
        M += (value - tmpM) / k;
        S += (value - tmpM) * (value - M);
    }
    return Math.Sqrt(S / (k-1));
}
 

2voto

dmckee Points 50318

Vous pouvez éviter de faire deux passes sur les données en accumulant la moyenne et la moyenne des carrés

cnt = 0
mean = 0
meansqr = 0
loop over array
    cnt++
    mean += value
    meansqr += value*value
mean /= cnt
meansqr /= cnt

et formant

sigma = sqrt(meansqr - mean^2)

Un facteur d' cnt/(cnt-1) est souvent approprié ainsi.

BTW-- Le premier passage sur les données de Demi et McWafflestix les réponses sont cachées dans les appels d' Average. Ce genre de chose est certainement trivial sur une petite liste, mais si la liste dépasse la taille de la mémoire cache, ou même l'ensemble de travail, cela devient une offre promo.

2voto

Demi Points 3547

Extrait de code:

 public static double StandardDeviation(List<double> valueList)
{
    if (valueList.Count < 2) return 0.0;
    double sumOfSquares = 0.0;
    double average = valueList.Average(); //.NET 3.0
    foreach (double value in valueList) 
    {
        sumOfSquares += Math.Pow((value - average), 2);
    }
    return Math.Sqrt(sumOfSquares / (valueList.Count - 1));
}
 

1voto

Paul Sonier Points 25528

Voici le code pour calculer un écart-type pour un ensemble de nombres. Une fois que vous avez cela, cela vous donne une limite supérieure et inférieure pour comparer le nombre.

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