使用MatPlotLib和Numpy拟合高斯分布到直方图 - Y轴缩放错误?

5 投票
1 回答
38405 浏览
提问于 2025-04-18 05:15

我写了下面的代码来把高斯曲线(也就是钟形曲线)拟合到一个直方图上。看起来是有效的,不过Y轴的缩放好像不太对。我哪里出错了呢?

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.mlab as mlab

list = [0,1,1,2,2,2,3,3,4]

plt.figure(1)
plt.hist(list)
plt.xlim((min(list), max(list)))

mean = np.mean(list)
variance = np.var(list)
sigma = np.sqrt(variance)
x = np.linspace(min(list), max(list),100)
plt.plot(x,mlab.normpdf(x,mean,sigma))

plt.show()

谢谢!

1 个回答

14

你需要对直方图进行归一化处理,因为你绘制的分布图也是经过归一化的:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.mlab as mlab

arr = np.random.randn(100)

plt.figure(1)
plt.hist(arr, density=True)
plt.xlim((min(arr), max(arr)))

mean = np.mean(arr)
variance = np.var(arr)
sigma = np.sqrt(variance)
x = np.linspace(min(arr), max(arr), 100)
plt.plot(x, mlab.normpdf(x, mean, sigma))

plt.show()

注意在调用 plt.hist 时使用了 density=True。另外,我还修改了你的样本数据,因为数据点太少的话,直方图看起来会很奇怪。

如果你想保留原始的直方图,而是调整分布的话,你需要对分布进行缩放,使得分布的积分等于直方图的积分,也就是列表中项目的数量乘以条形的宽度。可以这样实现:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.mlab as mlab

arr = np.random.randn(1000)

plt.figure(1)
result = plt.hist(arr)
plt.xlim((min(arr), max(arr)))

mean = np.mean(arr)
variance = np.var(arr)
sigma = np.sqrt(variance)
x = np.linspace(min(arr), max(arr), 100)
dx = result[1][1] - result[1][0]
scale = len(arr)*dx
plt.plot(x, mlab.normpdf(x, mean, sigma)*scale)

plt.show()

注意计算 scale 因子时,是用项目数量乘以单个条形的宽度。

撰写回答