name generate example comentarios c# math statistics standard-deviation

c# - generate - xml doc



Desviación estándar de la lista genérica? (4)

Esta pregunta ya tiene una respuesta aquí:

Necesito calcular la desviación estándar de una lista genérica. Trataré de incluir mi código. Es una lista genérica con datos en ella. La información es en su mayoría floats y ints. Aquí está mi código relacionado con él sin entrar en detalles:

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

Aquí está la función donde la desviación estándar necesita ser calculada:

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

Ignora qué está dentro de la función LatchStdev () porque estoy seguro de que no está bien. Es solo mi pobre intento de calcular el st dev. Sé cómo hacerlo de una lista de dobles, pero no de una lista de datos genéricos. Si alguien tuvo experiencia en esto, por favor ayuda.


Aunque la respuesta aceptada parece matemáticamente correcta, está mal desde la perspectiva de la programación: enumera la misma secuencia 4 veces. Esto podría estar bien si el objeto subyacente es una lista o una matriz, pero si la entrada es una expresión filtrada / agregada / etc linq, o si los datos provienen directamente de la base de datos o la corriente de red, esto causaría un rendimiento mucho menor.

Recomiendo encarecidamente no reinventar la rueda y utilizar una de las mejores bibliotecas matemáticas de código abierto Math.NET. Hemos estado usando esa lib en nuestra compañía y estamos muy contentos con el rendimiento.

PM> Install-Package MathNet.Numerics

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

Consulte http://numerics.mathdotnet.com/docs/DescriptiveStatistics.html para obtener más información.

Por último, para aquellos que desean obtener el resultado más rápido posible y sacrificar algo de precisión, lea el algoritmo de "paso único" https://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods


El ejemplo anterior es ligeramente incorrecto y podría tener un error de división por cero si su conjunto de población es 1. El siguiente código es algo más simple y da el resultado de "desviación estándar de población". ( 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<double> values) { double avg = values.Average(); return Math.Sqrt(values.Average(v=>Math.Pow(v-avg,2))); } }


Veo lo que estás haciendo, y uso algo similar. Me parece que no vas lo suficientemente lejos. Tiendo a encapsular todo el procesamiento de datos en una sola clase, de esa manera puedo almacenar en caché los valores que se calculan hasta que la lista cambie. por ejemplo:

public class StatProcessor{ private list<double> _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 } }

Notará que al usar este método, solo la primera solicitud de promedio realmente calcula el promedio. Después de eso, siempre y cuando no agreguemos (o eliminemos, o modifiquemos en absoluto, pero se muestren) algo de la lista, podemos obtener el promedio de básicamente nada.

Además, dado que el promedio se usa en el algoritmo para la desviación estándar, calcular primero la desviación estándar nos dará el promedio de forma gratuita, y calcular el promedio primero nos dará un pequeño aumento en el rendimiento en el cálculo de devatación estándar, suponiendo que recuerdemos revisa la bandera.

¡Además! lugares como la función promedio, en la que ya se repite todo valor de todos modos, es un buen momento para almacenar en caché cosas como los valores mínimo y máximo. Por supuesto, las solicitudes de esta información deben verificar primero si han sido almacenadas en caché, y eso puede causar una desaceleración relativa en comparación con solo encontrar el máximo usando la lista, ya que hace todo el trabajo extra configurando todos los cachés en cuestión, no solo el uno a tu acceso.


Este artículo debería ayudarte. Crea una función que calcula la desviación de una secuencia de valores double . Todo lo que tiene que hacer es proporcionar una secuencia de elementos de datos apropiados.

La función resultante es:

private double CalculateStdDev(IEnumerable<double> 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; }

Esto es bastante fácil de adaptar para cualquier tipo genérico, siempre que proporcionemos un selector para el valor que se calcula. LINQ es ideal para eso, la función Select permite proyectar desde su lista genérica de tipos personalizados una secuencia de valores numéricos para los cuales calcular la desviación estándar:

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