通用名单的标准偏差?
我需要计算一个通用列表的标准偏差。 我会尽量包括我的代码。 它是一个包含数据的通用列表。 数据大部分是浮动和整数。 这是我的代码是相对于它没有得到很多的细节:
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); }
以下是需要计算标准差的function:
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)); } } }
忽略LatchStdev()函数中的内容,因为我确定它不正确。 它只是我可怜的企图计算st dev。 我知道如何做一个双打列表,但不是通用数据列表的列表。 如果有人有这方面的经验,请帮助。
这篇文章应该帮助你。 它创build一个函数来计算一系列double
值的偏差。 你所要做的就是提供一系列适当的数据元素。
由此产生的function是:
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; }
这很容易适应任何genericstypes,只要我们为正在计算的值提供一个select器即可。 LINQ非常适合这样的情况, Select
函数允许您从自定义types的通用列表项目中计算标准偏差的一系列数值:
List<ValveData> list = ... var result = list.Select( v => (double)v.SomeField ) .CalculateStdDev();
上面的例子稍微有点不正确,如果你的人口数量是1,那么可以有一个除以零的错误。下面的代码是比较简单的,并给出了“总体标准偏差”结果。 ( 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))); } }
即使被接受的答案在math上是正确的,但从编程的angular度来看是错误的 – 它列举了4次相同的序列。 如果底层对象是一个列表或一个数组,但是如果input是一个过滤/聚合/ etc的linqexpression式,或者数据直接来自数据库或networkingstream,这可能会好起来,这会导致性能低得多。
我强烈build议不要重新发明轮子,并使用一个更好的开源math库Math.NET。 我们一直在我们公司使用这个lib,对这个性能非常满意。
PM>安装包MathNet.Numerics
var populationStdDev = new List<double>(1d, 2d, 3d, 4d, 5d).PopulationStandardDeviation(); var sampleStdDev = new List<double>(2d, 3d, 4d).StandardDeviation();
有关更多信息,请参阅http://numerics.mathdotnet.com/docs/DescriptiveStatistics.html 。
最后,对于想要获得最快结果并牺牲一些精度的用户,请阅读“单程”algorithmhttps://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods
我明白你在做什么,并且使用类似的东西。 在我看来,你还远远不够。 我倾向于将所有数据处理封装到一个类中,这样我可以caching计算的值,直到列表更改为止。 例如:
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 } }
你会注意到,使用这个方法,只有平均的第一个请求实际上是计算平均值。 之后,只要我们不添加(或删除,或修改,但显示的那些),从列表中的任何东西,我们可以得到基本上什么都没有。
另外,由于标准偏差algorithm中使用的是平均值,所以首先计算标准偏差会给我们免费的平均值,而计算平均值首先会使我们在标准偏差计算中有一点性能提升,假设我们记得检查国旗。
此外! 就像平均函数一样,在这里你已经循环了每一个值,是一个很好的时间来caching最小值和最大值。 当然,这个信息的请求首先需要检查它们是否被caching,并且相对于仅仅使用列表来查找最大值而言会导致相对减慢,因为它完成了所有有关caching的所有额外工作,而不仅仅是一个你的访问。