69

一般的なリストの標準偏差を計算する必要があります。コードを含めようとします。データを含む一般的なリスト。データは主にfloatとintです。これは、詳細に立ち入ることなく、それに関連する私のコードです。

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

標準偏差を計算する必要がある関数は次のとおりです。

        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()関数内の内容は、正しくないと確信しているため、無視してください。stdevを計算するのは私の貧弱な試みです。私はdoubleのリストでそれを行う方法を知っていますが、一般的なデータリストのリストではありません。誰かがこれを経験したことがあれば、助けてください。

4

4 に答える 4

183

上記の例は少し正しくなく、母集団セットが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)));
    }
}
于 2011-06-06T12:57:22.070 に答える
79

この記事はあなたを助けるはずです。一連のdouble値の偏差を計算する関数を作成します。あなたがしなければならないのは、適切なデータ要素のシーケンスを提供することです。

結果の関数は次のとおりです。

private double CalculateStandardDeviation(IEnumerable<double> values)
{   
  double standardDeviation = 0;

  if (values.Any()) 
  {      
     // 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.      
     standardDeviation = Math.Sqrt((sum) / (values.Count()-1));   
  }  

  return standardDeviation;
}

これは、計算される値のセレクターを提供する限り、あらゆるジェネリック型に適応するのに十分簡単です。LINQはそのために最適です。このSelect機能を使用すると、カスタムタイプの汎用リストから、標準偏差を計算するための一連の数値を投影できます。

List<ValveData> list = ...
var result = list.Select( v => (double)v.SomeField )
                 .CalculateStdDev();
于 2010-06-29T14:39:16.117 に答える
27

受け入れられた答えは数学的には正しいように見えますが、プログラミングの観点からは間違っています。同じシーケンスを4回列挙します。基になるオブジェクトがリストまたは配列である場合、これは問題ない可能性がありますが、入力がフィルター処理/集約などのlinq式である場合、またはデータがデータベースまたはネットワークストリームから直接取得される場合、パフォーマンスが大幅に低下します。

車輪の再発明をせず、より優れたオープンソースの数学ライブラリMath.NETの1つを使用することを強くお勧めします。私たちはその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を参照してください。

最後に、可能な限り最速の結果を得て、ある程度の精度を犠牲にしたい場合は、「ワンパス」アルゴリズムhttps://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methodsをお読みください。

于 2012-04-13T19:49:05.717 に答える
0

私はあなたが何をしているのかわかります、そして私は似たようなものを使います。あなたは十分に進んでいないように私には思えます。私はすべてのデータ処理を単一のクラスにカプセル化する傾向があります。そうすれば、リストが変更されるまで計算された値をキャッシュできます。例えば:

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

この方法を使用すると、平均の最初のリクエストのみが実際に平均を計算することに気付くでしょう。その後、リストから何も追加(または削除、変更はしませんが、それらは表示されます)しない限り、基本的に何も平均を得ることができません。

さらに、平均は標準偏差のアルゴリズムで使用されるため、最初に標準偏差を計算すると無料で平均が得られ、最初に平均を計算すると、標準偏差の計算でパフォーマンスが少し向上します。フラグを確認してください。

さらに!とにかくすべての値をループしている平均関数のような場所は、最小値や最大値などをキャッシュする絶好の機会です。もちろん、この情報のリクエストは、最初にキャッシュされているかどうかを確認する必要があります。これにより、リストを使用して最大値を見つける場合に比べて、関連するすべてのキャッシュだけでなく、関連するすべてのキャッシュを設定するための余分な作業がすべて行われるため、比較的遅くなる可能性があります。 1つはアクセスします。

于 2012-10-29T17:08:15.950 に答える