我被要求在我们的数据上绘制一个正态分布覆盖的直方图。我们的数据是一系列无限范围的双打。接下来的想法是:
这是我到目前为止所写的内容:
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);
但结果看起来有点奇怪:
直方图似乎与叠加层不匹配。感觉我错过了什么 - 要么计算错误的桶,要么在数学上有错误。
答案 0 :(得分:1)
这个问题现在很陈旧,但我在尝试做类似的事情时发现了这个问题,所以我会提出这个建议:
首先,varianceSq
变量实际上应该是方差(或标准偏差的平方)。
其次,从平均值和标准偏差计算f
的标准公式使得曲线的面积比其低1。要匹配直方图,您需要将值向上缩放直方图矩形的总面积
即。 y = f * (bar width * total of bar heights)
。
答案 1 :(得分:0)
嘿,谢谢你指出了正确的类型,以便首先建立一个像样的直方图。
我想说通过逐步通过数据库而不是单步执行值来对覆盖代码进行另一次破解。