Écart type de la liste générique?

Je dois calculer l’écart type d’une liste générique. Je vais essayer d’inclure mon code. C’est une liste générique contenant des données. Les données sont principalement des flotteurs et des ints. Voici mon code qui lui est relatif sans entrer dans les détails:

namespace ValveTesterInterface { public class ValveDataResults { private List m_ValveResults; public ValveDataResults() { if (m_ValveResults == null) { m_ValveResults = new List(); } } public void AddValveData(ValveData valve) { m_ValveResults.Add(valve); } 

Voici la fonction où l’écart type doit être calculé:

  public float LatchStdev() { float sumOfSqrs = 0; float meanValue = 0; foreach (ValveData value in m_ValveResults) { meanValue += value.LatchTime; } meanValue = (meanValue / m_ValveResults.Count) * 0.02f; for (int i = 0; i <= m_ValveResults.Count; i++) { sumOfSqrs += Math.Pow((m_ValveResults - meanValue), 2); } return Math.Sqrt(sumOfSqrs /(m_ValveResults.Count - 1)); } } } 

Ignorer ce qui se trouve à l’intérieur de la fonction LatchStdev () car je suis sûr que ce n’est pas correct. C’est juste ma pauvre tentative de calculer le dev. Je sais le faire d’une liste de doubles, mais pas d’une liste de données génériques. Si quelqu’un a de l’expérience, aidez-le.

Cet article devrait vous aider. Il crée une fonction qui calcule l’écart d’une séquence de valeurs double . Il vous suffit de fournir une séquence d’éléments de données appropriés.

La fonction résultante est:

 private double CalculateStdDev(IEnumerable values) { double ret = 0; if (values.Count() > 0) { //Compute the Average double avg = values.Average(); //Perform the Sum of (value-avg)_2_2 double sum = values.Sum(d => Math.Pow(d - avg, 2)); //Put it all together ret = Math.Sqrt((sum) / (values.Count()-1)); } return ret; } 

Ceci est assez facile à adapter à tout type générique, à condition que nous fournissions un sélecteur pour la valeur en cours de calcul. LINQ est idéal pour cela, la fonction de Select vous permet de projeter à partir de votre liste générique de types personnalisés une séquence de valeurs numériques pour calculer l’écart-type:

 List list = ... var result = list.Select( v => (double)v.SomeField ) .CalculateStdDev(); 

L’exemple ci-dessus est légèrement incorrect et pourrait entraîner une division par zéro si votre ensemble de population est égal à 1. Le code suivant est quelque peu plus simple et donne le résultat «écart type de population». ( http://en.wikipedia.org/wiki/Standard_deviation )

 using System; using System.Linq; using System.Collections.Generic; public static class Extend { public static double StandardDeviation(this IEnumerable values) { double avg = values.Average(); return Math.Sqrt(values.Average(v=>Math.Pow(v-avg,2))); } } 

Même si la réponse acceptée semble mathématiquement correcte, elle est erronée du sharepoint vue de la programmation – elle énumère la même séquence 4 fois. Cela pourrait être correct si l’object sous-jacent est une liste ou un tableau, mais si l’entrée est une expression / etc linq filtrée / agrégée, ou si les données proviennent directement de la firebase database ou du stream réseau,

Je recommande fortement de ne pas réinventer la roue et d’utiliser l’une des meilleures bibliothèques mathématiques Open Source Math.NET. Nous avons utilisé cette lib dans notre société et sums très satisfaits de la performance.

PM> Package d’installation MathNet.Numerics

 var populationStdDev = new List(1d, 2d, 3d, 4d, 5d).PopulationStandardDeviation(); var sampleStdDev = new List(2d, 3d, 4d).StandardDeviation(); 

Voir http://numerics.mathdotnet.com/docs/DescriptiveStatistics.html pour plus d’informations.

Enfin, pour ceux qui veulent obtenir le résultat le plus rapide possible et sacrifier une certaine précision, lisez l’algorithme “one-pass” https://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods

Je vois ce que tu fais et j’utilise quelque chose de similaire. Il me semble que tu ne vas pas assez loin. J’ai tendance à encapsuler tout le traitement des données dans une seule classe, de cette façon, je peux mettre en cache les valeurs calculées jusqu’à ce que la liste change. par exemple:

 public class StatProcessor{ private list _data; //this holds the current data private _avg; //we cache average here private _avgValid; //a flag to say weather we need to calculate the average or not private _calcAvg(); //calculate the average of the list and cache in _avg, and set _avgValid public double average{ get{ if(!_avgValid) //if we dont HAVE to calculate the average, skip it _calcAvg(); //if we do, go ahead, cache it, then set the flag. return _avg; //now _avg is garunteed to be good, so return it. } } ...more stuff Add(){ //add stuff to the list here, and reset the flag } } 

Vous remarquerez qu’en utilisant cette méthode, seule la première demande de moyenne calcule réellement la moyenne. Après cela, tant que nous n’ajoutons pas (ou ne supprimons ou ne modifions pas du tout, mais que ceux-ci ne sont pas montrés) quelque chose de la liste, nous pouvons obtenir la moyenne pour pratiquement rien.

De plus, puisque la moyenne est utilisée dans l’algorithme pour l’écart type, le calcul de l’écart type en premier nous donnera la moyenne gratuitement, et le calcul en premier nous donnera un petit coup de pouce au calcul de la déviation standard. vérifiez le drapeau.

En outre! des endroits comme la fonction moyenne, où vous parcourez déjà toutes les valeurs de toute façon, constituent le moment idéal pour mettre en cache des éléments tels que les valeurs minimales et maximales. Bien sûr, les requêtes pour cette information doivent d’abord vérifier si elles ont été mises en cache, ce qui peut entraîner un ralentissement relatif par rapport à la simple recherche de la liste, car elle met tout en œuvre pour configurer tous les caches concernés. un votre access.