matplotlib 归一化直方图y轴大于1

dgtucam1  于 2023-10-24  发布在  其他
关注(0)|答案(1)|浏览(210)

有时当我创建一个直方图时,使用seaborn的histot函数,norm_hist = True,y轴小于1,就像PDF所期望的那样。其他时候它的值大于1。
例如,如果我跑

sns.set(); 
x = np.random.randn(10000)
ax = sns.distplot(x)

然后直方图上的y轴如预期的那样从0.0变为0.4,但是如果数据不是正态的,即使norm_hist = True,y轴也可以大到30。
我在直方图函数的归一化参数中遗漏了什么,例如sns.distplot的norm_hist?即使我自己通过创建一个新变量来归一化数据,如下所示:

new_var = data/sum(data)

因此,数据总和为1,无论norm_hist参数是否为True,y轴仍将显示远大于1的值(例如30)。
当y轴有如此大的范围时,我给予什么解释呢?
我认为发生的事情是我的数据集中在零附近,所以为了使数据的面积等于1(例如在kde下),直方图的高度必须大于1.
还有,我怎样才能让这些函数在y轴上显示概率呢?

krugob8w

krugob8w1#

规则并不是所有的条形图的面积之和应该等于1,而是所有条形图的面积之和应该等于1。当条形图非常窄时,尽管它们的面积之和等于1,但它们的面积之和可能相当大。条形图的高度乘以其宽度是一个值都在该范围内的概率。要使高度等于概率,你需要宽度为1的条形图。
这里有一个例子来说明发生了什么。

import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns

fig, axs = plt.subplots(ncols=2, figsize=(14, 3))

np.random.seed(2023)
a = np.random.normal(0, 0.01, 100000)
sns.histplot(a, bins=np.arange(-0.04, 0.04, 0.001), stat='density', ax=axs[0])
axs[0].set_title('Measuring in meters')
axs[0].containers[1][40].set_color('r')

a *= 1000
sns.histplot(a, bins=np.arange(-40, 40, 1), stat='density', ax=axs[1])
axs[1].set_title('Measuring in milimeters')
axs[1].containers[1][40].set_color('r')

plt.show()

左边的图使用0.001米宽的箱。最高的箱(红色)约为40高。值福尔斯落入该箱的概率为40*0.001 = 0.04
右边的图使用完全相同的数据,但以毫米为单位。现在的bin是1 mm宽。最高的bin大约是0.04高。一个值福尔斯落入该bin的概率也是0.04,因为bin宽度是1
作为概率密度函数具有大于1的区域的分布的示例,参见Pareto distributionα = 3
通过直接使用plt.hist(返回bin边缘和高度),可以轻松计算面积。

np.random.seed(2023)
a = np.random.normal(0, 0.01, 100000)
v = plt.hist(a, bins=np.arange(-0.04, 0.04, 0.001), density=True, ec='k')

left = v[1][:-1]
right = v[1][1:]
area = (v[0] * (right-left)).sum()

print(f'Area: {area}')

sns.distplot已弃用

import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns

fig, axs = plt.subplots(ncols=2, figsize=(14, 3))

a = np.random.normal(0, 0.01, 100000)
sns.distplot(a, bins=np.arange(-0.04, 0.04, 0.001), ax=axs[0])
axs[0].set_title('Measuring in meters')
axs[0].containers[0][40].set_color('r')

a *= 1000
sns.distplot(a, bins=np.arange(-40, 40, 1), ax=axs[1])
axs[1].set_title('Measuring in milimeters')
axs[1].containers[0][40].set_color('r')

plt.show()

相关问题