web-dev-qa-db-fra.com

Comment calculer un écart-type [tableau]

double[] someDoubles = { 34.6, 45.1, 55.5, 78.5, 84.66, **1400.32**, 99.04, 103.99 };

Ce code ci-dessus est un exemple abrégé d'un comportement inattendu d'un algorithme cumulatif (voir la valeur en gras). En réalité, il s'agit d'une classe qui contient également une date avec chaque valeur.

C # Calculer un écart? Un algorithme qui trie les lignes qui rompt la chaîne cumulative?

Les conseils sont utiles,

[INSÉRER]

Pour clarifier, il s'agit de trois choses
Les performances sont vraiment importantes sur ce sujet.

First: Fast-Scan si les valeurs suivent un modèle cumulatif.
Second: Vérifiez si toutes les valeurs sont dans un écart raisonnable.
Troisième: Soulignez et faites la gestion des erreurs.

Cette question concerne la première et la seconde.

26
Independent

Utilisation de LINQ:

double average = someDoubles.Average();
double sumOfSquaresOfDifferences = someDoubles.Select(val => (val - average) * (val - average)).Sum();
double sd = Math.Sqrt(sumOfSquaresOfDifferences / someDoubles.Length); 

La variable sd aura l'écart type.

Si tu as un List<double>, puis utilisez someDoubles.Count dans la dernière ligne pour le code au lieu de someDoubles.Length.

63

Pour calculer l'écart type, vous pouvez utiliser ce code. Tiré directement de Calculer l'écart type des variables doubles en C # par Victor Chen.

private double getStandardDeviation(List<double> doubleList)  
{  
   double average = doubleList.Average();  
   double sumOfDerivation = 0;  
   foreach (double value in doubleList)  
   {  
      sumOfDerivation += (value) * (value);  
   }  
   double sumOfDerivationAverage = sumOfDerivation / (doubleList.Count - 1);  
   return Math.Sqrt(sumOfDerivationAverage - (average*average));  
}  

Ce lien vers le site de Victor ne fonctionne plus, mais est toujours inclus pour aider à maintenir l'attribution.

14
jb.

Étant donné les valeurs aberrantes, vous pourriez trouver la plage interquartile plus utile que l'écart-type. C'est simple à calculer: il suffit de trier les nombres et de trouver la différence des valeurs au 75e centile et au 25e centile.

3
Michael J. Barber

Vous avez déjà de bonnes réponses sur le calcul de l'écart-type, mais j'aimerais ajouter algorithme de Knuth pour calculer la variance à la liste. L'algo de Knuth effectue le calcul en un seul passage sur les données. L'écart type n'est alors que la racine carrée de la variance, comme indiqué ci-dessus. L'algorithme de Knuth vous permet également de calculer des valeurs intermédiaires de la variance au fur et à mesure, si cela s'avère utile.

Re: "Fast-Scan si les valeurs suivent un modèle cumulatif", si vos données devraient croître linéairement, je suggère de calculer une moyenne et une variance pour la différence entre les éléments successifs (10,5, 10,4 et 23,0 seraient les trois premières valeurs de différence de vos données). Recherchez ensuite les valeurs aberrantes de ces valeurs de différence au lieu des points de données. Cela rendra les valeurs de données anormales comme 1400.32 dans votre exemple beaucoup plus évidentes, en particulier lorsque les données deviennent finalement suffisamment grandes pour que 1400 soit proche de la moyenne.

3
PaulF

Si vous êtes sur .NET 4.0, les liens suivants peuvent être utiles
Écart type dans LINQ
http://msdn.Microsoft.com/en-us/library/dd456873.aspx

2
Anton Semenov

Dans VB.Net, codez pour l'écart-type, le score Z et NormSDist. J'ai coupé et collé du code de travail et l'ai modifié pour qu'il soit plus générique. J'ai peut-être introduit des problèmes. De plus, je ne suis pas un mathématicien alors méfiez-vous.

Public Property SumOfSquaresOfDifferences As Double ' calculated elsewhere

Public ReadOnly Property StdOfTotalMatches As Double
    Get
        If NumberOfTickets = 0 Then Return 0
        Return Math.Sqrt(SumOfSquaresOfDifferences / NumberOfTickets)
    End Get
End Property

Public ReadOnly Property zScoreOfTotalMatches As Double
    Get
        If StdOfTotalMatches = 0 Then Return 0
        Return (TotalMatches / NumberOfTickets - AverageMatches) / StdOfTotalMatches
    End Get
End Property

Public ReadOnly Property NormSDistOfTotalMatches As Double
    Get
        Return NormSDist(zScoreOfTotalMatches)
    End Get
End Property

Public ReadOnly Property AverageMatches As Double
    Get
        Return If(NumberOfTickets, TotalMatches / NumberOfTickets, 0)
    End Get
End Property

Shared Function NormSDist(ByVal zScore As Double) As Double
    Dim ErfResult As Double = Erf(zScore / Math.Sqrt(2.0))
    Dim res As Double = ErfResult + (1 - ErfResult) / 2
    Return If(zScore < 0, 1 - res, res)
End Function

Shared Function Erf(ByVal n As Double) As Double

    Dim t As Double = 1.0 / (1.0 + 0.5 * Math.Abs(n))

    ' use Horner's method - thanks to http://bytes.com/topic/c-sharp/answers/240995-normal-distribution
    Dim d As Double = 1 - t * Math.Exp(-n * n - 1.26551223 + _
    t * (1.00002368 + _
    t * (0.37409196 + _
    t * (0.09678418 + _
    t * (-0.18628806 + _
    t * (0.27886807 + _
    t * (-1.13520398 + _
    t * (1.48851587 + _
    t * (-0.82215223 + _
    t * (0.17087277))))))))))

    'Return If(d >= 0, d, 1 - d)
    Return d

End Function
0
BSalita