double[] someDoubles = { 34.6, 45.1, 55.5, 78.5, 84.66, **1400.32**, 99.04, 103.99 };
上記のコードは、累積アルゴリズムの予期しない動作の簡単なサンプルです(太字の値を参照)。実際には、これは各値を持つ日付も保持するクラスです。
C#偏差を計算しますか?累積チェーンを破る行を整理するアルゴリズム?
アドバイスは助けになります
[INSERT]
明確にするために、これは約3つのことです
このトピックのパフォーマンスは本当に重要です。
最初:値が累積パターンに従う場合は高速スキャン。
Second:すべての値が妥当な偏差になるかどうかを確認します。
番目:指摘してエラー処理を行います。
この質問は、1番目と2番目についてです。
LINQの使用:
double average = someDoubles.Average();
double sumOfSquaresOfDifferences = someDoubles.Select(val => (val - average) * (val - average)).Sum();
double sd = Math.Sqrt(sumOfSquaresOfDifferences / someDoubles.Length);
sd
変数には標準偏差があります。
List<double>
がある場合、someDoubles.Count
の代わりにコードの最後の行でsomeDoubles.Length
を使用します。
標準偏差を計算するには、このコードを使用できます。 Victor ChenによるC#の二重変数の標準偏差の計算から直接取得。
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));
}
これは Victorのサイトへのリンク は機能しませんが、属性を維持するために含まれています。
外れ値を考えると、 四分位範囲 が標準偏差よりも有用であることがわかります。これは計算が簡単です。数値を並べ替えて、75パーセンタイルと25パーセンタイルで値の差を見つけるだけです。
標準偏差の計算についてはすでにいくつかの良い答えがありますが、リストに分散を計算するために Knuthのアルゴリズム を追加したいと思います。 Knuthのアルゴリズムは、データの1回のパスで計算を実行します。上記で指摘したように、標準偏差は分散の平方根になります。 Knuthのアルゴリズムを使用すると、分散の中間値を計算することもできます(有用な場合)。
Re:「値が累積パターンに従う場合は高速スキャン」、データが線形に増加すると予想される場合は、連続する要素間で差の平均と分散を計算することをお勧めします(10.5、10.4 23.0はデータからの最初の3つの差分値です)。次に、データポイントではなく、これらの差分値の外れ値を見つけます。これにより、例の1400.32のような異常なデータ値がより明確になります。特に、データが最終的に1400が平均に近づくほど大きくなる場合に顕著です。
.NET 4.0を使用している場合、次のリンクが役立ちます。
LINQの標準偏差
http://msdn.Microsoft.com/en-us/library/dd456873.aspx
VB.Netで、標準偏差、Zスコア、およびNormSDistのコード。作業コードから切り取って貼り付け、より一般的なコードに変更しました。問題が発生した可能性があります。また、私は数学の男ではないので注意してください。
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