【问题标题】:Draw histogram with normal distribution overlay from data从数据中绘制具有正态分布叠加的直方图
【发布时间】:2014-11-25 18:28:27
【问题描述】:

我被要求在我们的数据上绘制一个正态分布叠加的直方图。我们的数据是一个无限范围的双精度数组。接下来是思路:

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

但是结果看起来有点奇怪:

直方图似乎与叠加层不匹配。感觉就像我错过了一些东西 - 要么计算错误,要么在数学上有错误。

【问题讨论】:

    标签: c# statistics oxyplot


    【解决方案1】:

    这个问题现在已经很陈旧了,但是我在尝试做类似的事情时发现了它,所以我会提供这个建议:

    首先,varianceSq 变量实际上应该是方差(或标准差的平方)。

    其次,根据平均值和标准差计算f 的标准公式会生成一条面积为 1 的曲线。要匹配直方图,您需要将值按直方图矩形的总面积放大

    y = f * (bar width * total of bar heights).

    【讨论】:

    • 谢谢!我错过了这个地区。很好的解释。
    【解决方案2】:

    您好,感谢您一开始就为我指出了正确的类型以构建体面的直方图。

    我会说通过逐步检查 bin 而不是逐步检查值来对覆盖代码进行另一次破解。

    【讨论】: