我对matplotlib的hist()函数有疑问。
我正在编写一个代码来绘制数值的直方图,其值从0到1不等。例如:
values = [0.21, 0.51, 0.41, 0.21, 0.81, 0.99]
bins = np.arange(0, 1.1, 0.1)
a, b, c = plt.hist(values, bins=bins, normed=0)
plt.show()
上面的代码生成了一个正确的直方图(由于我没有足够的声誉,我无法发布图像)。就频率而言,它看起来像:
[0 0 2 0 1 1 0 0 1 1]
我想将此输出转换为离散概率质量函数,即对于上面的示例,我想获得以下频率值:
[ 0. 0. 0.333333333 0. 0.166666667 0.166666667 0. 0. 0.166666667 0.166666667 ] # each item in the previous array divided by 6)
我认为我只需要将hist()函数中的参数更改为'normed = 1'。但是,我得到以下直方图频率:
[ 0. 0. 3.33333333 0. 1.66666667 1.66666667 0. 0. 1.66666667 1.66666667 ]
这不是我所期望的,我不知道如何得到离散概率质量函数,其总和应为1.0。在以下链接(link to the question)中提出了类似的问题,但我认为这个问题没有得到解决。
我提前感谢您的帮助。
答案 0 :(得分:6)
原因是norm=True
给出了probability density function。在概率论中,概率密度函数或连续随机变量的密度描述了该随机变量对给定值的相对可能性。
让我们考虑一个非常简单的例子。
x=np.arange(0.1,1.1,0.1)
array([ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
# Bin size
bins = np.arange(0.05, 1.15, 0.1)
np.histogram(x,bins=bins,normed=1)[0]
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]
np.histogram(x,bins=bins,normed=0)[0]/float(len(x))
[ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
# Change the bin size
bins = np.arange(0.05, 1.15, 0.2)
np.histogram(x,bins=bins,normed=1)[0]
[ 1., 1., 1., 1., 1.]
np.histogram(x,bins=bins,normed=0)[0]/float(len(x))
[ 0.2, 0.2, 0.2, 0.2, 0.2]
正如您在上面所看到的,x在[0.05-0.15]
或[0.15-0.25]
之间的概率为1/10
,而如果您将bin大小更改为0.2
则它位于[0.05-0.25]
或[0.25-0.45]
之间的概率为1/5
。现在这些实际概率值取决于箱尺寸,但是,概率密度与箱尺寸无关。因此,这是完成上述操作的唯一正确方法,否则需要在每个图中说明bin宽度。
因此,在您的情况下,如果您真的想要绘制每个区间的概率值(而不是概率密度),那么您可以简单地将每个直方图的频率除以总元素的数量。但是,我建议你不要这样做,除非你正在使用离散变量,并且你的每个箱子都代表了这个变量的一个可能值。
答案 1 :(得分:0)
从直方图绘制连续概率函数(PDF) - 用Python解决。请参阅此blog以获取详细说明。 (http://howdoudoittheeasiestway.blogspot.com/2017/09/plotting-continuous-probability.html) 否则,您可以使用以下代码。
n, bins, patches = plt.hist(A, 40, histtype='bar')
plt.show()
n = n/len(A)
n = np.append(n, 0)
mu = np.mean(n)
sigma = np.std(n)
plt.bar(bins,n, width=(bins[len(bins)-1]-bins[0])/40)
y1= (1/(sigma*np.sqrt(2*np.pi))*np.exp(-(bins - mu)**2 /(2*sigma**2)))*0.03
plt.plot(bins, y1, 'r--', linewidth=2)
plt.show()