3

データに正規分布を重ねてヒストグラムを描くように依頼されました。私たちのデータは、範囲が無制限の double の配列です。アイデアは次のとおりです。

  1. すべての値をバケットに分割します (コードではステップと呼びます)
  2. 各バケット内にあるすべての値を見つける
  3. バケット内のアイテム数を計算し、それらを全体のアイテム数で割ります
  4. mu を avg(values) として計算
  5. 分散を avg([(各値 - mu)^2]) として計算します
  6. 数式でオーバーレイを描画: 1. / Sqrt(2 * Pi * var)* e^((-(x - mean)^2 / 2 / var)

これまでに書いたものは次のとおりです。

double[] values;
const int StepsNumber = 30;
// Choosing the size of each bucket
double step = (values.Max() - values.Min())/StepsNumber;

double mean = values.Average();
double deviationSq = values.Select(x => Math.Pow(x - mean, 2)).Average();

var bucketeer = new Dictionary<double, double>();
for (double curr = values.Min(); curr <= values.Max(); curr += step)
{
        // Counting the values that can be put in the bucket and dividing them on values.Count()
        var count = values.Where(x => x >= fromVal && x < fromVal + step).Count();
        bucketeer.Add(fromVal, count / values.Count());
}

// Then I build normal distribution overlay 
var overlayData = new LineSeries();
int x0 = values.Min();
int x1 = values.Max();
for (int i = 0; i < n; i++)
        {
            double x = x0 + (x1 - x0) * i / (n - 1);
            double f = 1.0 / Math.Sqrt(2 * Math.PI * varianceSq) * Math.Exp(-(x - mean) * (x - mean) / 2 / varianceSq);
            overlayData .Points.Add(new DataPoint(x, f));
        }

// And draw everything

plotModel.Series.Add(overlayData);
        foreach (var pair in bucketeer.OrderBy(x => x.Key))
        {
            columnSeries.Items.Add(new RectangleBarItem(pair.Key, 0, pair.Key + step, pair.Value));
        }
plotModel.Series.Add(columnSeries);

しかし、結果は少し奇妙に見えます。 マイチャート

ヒストグラムがオーバーレイと一致していないようです。バケットの計算が間違っているか、計算に誤りがあるかのどちらかです。

4

2 に答える 2