从数据中绘制带有正态分布曲线的直方图

3
我被要求对我们的数据绘制具有正态分布覆盖的直方图。 我们的数据是一个无限范围的双精度数组。 思路如下:
  1. 将所有值分成桶(我在我的代码中称之为步骤)
  2. 找到每个桶内的所有值
  3. 计算桶中项目的数量并将它们除以整体项目数
  4. 计算mu的平均值
  5. 计算variance作为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);

但是结果看起来有点奇怪: 我的图表 直方图似乎与叠加图不匹配。感觉好像我漏掉了什么——可能是计算桶时出错了,或者数学上有误。
2个回答

3
这个问题已经很老了,但我在尝试做类似的事情时发现了它,所以我要提供以下建议:
首先,变量varianceSq实际上应该是方差(或标准差平方)。
其次,从均值和标准差计算f的标准公式产生的曲线在其下方有一个面积为1。为了与直方图相匹配,您需要将值放大到直方图矩形的总面积上,
即y = f * (bar width * total of bar heights)。

谢谢!我漏掉了这个区域。解释得很好。 - lnjuanj

0

嘿,感谢您指导我如何首先构建一个不错的直方图所需的正确类型。

我建议您尝试通过遍历直方图中的区间而不是值来改进叠加代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接