使用MatPlotLib和Numpy拟合高斯分布到直方图 - Y轴缩放错误?
我写了下面的代码来把高斯曲线(也就是钟形曲线)拟合到一个直方图上。看起来是有效的,不过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
因子时,是用项目数量乘以单个条形的宽度。