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

5

我写了下面的代码来将高斯曲线拟合到直方图中。它似乎可以工作,尽管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()

谢谢!


3
建议更改列表名称,避免与类型"list"冲突。 - kd88
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


谢谢,它运行良好。有没有一种方法,可以不将直方图归一化到分布上,而是一开始就不归一化分布?我在Python方面非常初学,更不用说MatPlotLib了。 - El Confuso
1
当然,您可以将分布乘以直方图中的箱子数除以总项数。这样应该可以得到您想要的结果。 - David Zwicker
请问能否给个例子? - El Confuso
2
列表 = np.random.randn(1000) 这段代码重新定义了list()关键字。这是一种糟糕的做法,会创建非常难以调试的问题。 - Lidia Freitas
matplotlib.pyplot.hist 不再有名为 normed 的参数(在 matplotlib 版本 3.0.2 中已被弃用)。它已被 density 参数替换。 - Tomás Ferrer
显示剩余2条评论

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