标准化的直方图y轴大于1

5
有时候,当我使用seaborn的displot函数创建直方图时,如果norm_hist参数设置为True,则y轴值将小于1,这符合概率密度函数(PDF)的预期。但有时候y轴的值会大于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,直方图的高度必须大于1...但由于概率不能超过1,那么结果意味着什么?
另外,我如何使这些函数在y轴上显示概率?
1个回答

20
规则并不是所有的条形图都应该加起来等于一。规则是所有条形图的面积加起来等于一。当条形图非常窄时,它们的总和可能非常大,尽管它们的面积加起来等于一。条形图的高度乘以宽度是值落在该范围内的概率。要使高度等于概率,你需要宽度为一的条形图。
以下是一个例子来说明正在发生的情况。
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()

enter image description here

左边的图使用宽度为0.001米的箱子。最高的箱子(红色)高约为40。值落入该箱子的概率为40 * 0.001 = 0.04。
右边的图使用相同的数据,但以毫米为单位测量。现在箱子宽度为1毫米。最高的箱子高约为0.04。值落入该箱子的概率也是0.04,因为箱子宽度为1。
作为一个概率密度函数具有大于1区域的分布示例,请参见具有α = 3的Pareto分布。
通过直接使用plt.hist,该函数返回箱子边缘和高度,可以轻松计算面积。
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}')

enter image description here


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()

demo plot


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