标准化直方图 y 轴大于 1

MHa*_*all 5 python matplotlib histogram density-plot seaborn

有时,当我使用seaborn的displot函数创建直方图时,norm_hist = True,y轴小于PDF的预期值1。其他时候它的值大于一。

例如,如果我跑

sns.set(); 
x = np.random.randn(10000)
ax = sns.distplot(x)
Run Code Online (Sandbox Code Playgroud)

然后,直方图上的 y 轴将按预期从 0.0 变为 0.4,但如果数据不正常,即使norm_hist = True,y 轴也可能会大到 30。

关于直方图函数的标准化参数,我缺少什么,例如 sns.distplot 的norm_hist?即使我自己通过创建一个新变量来标准化数据:

new_var = data/sum(data)
Run Code Online (Sandbox Code Playgroud)

这样数据总和为 1,无论norm_hist 参数是否为 True,y 轴仍将显示远大于 1 的值(例如 30)。

当 y 轴有这么大的范围时我可以给出什么解释?

我认为发生的情况是我的数据紧密集中在零附近,因此为了使数据的面积等于 1(例如在 kde 下),直方图的高度必须大于 1...但是由于概率不能大于 1 结果是什么意思?

另外,如何让这些函数在 y 轴上显示概率?

Joh*_*anC 20

规则并不是所有条形之和都应该为 1。规则是所有条形的所有面积之和应为 1。当条形非常窄时,尽管它们的面积总和为 1,但它们的总和可能会相当大。条形的高度乘以宽度就是某个值全部位于该范围内的概率。为了使高度等于概率,您需要宽度为 1 的条形。

\n

这是一个例子来说明发生了什么。

\n
import numpy as np\nfrom matplotlib import pyplot as plt\nimport seaborn as sns\n\nfig, axs = plt.subplots(ncols=2, figsize=(14, 3))\n\nnp.random.seed(2023)\na = np.random.normal(0, 0.01, 100000)\nsns.histplot(a, bins=np.arange(-0.04, 0.04, 0.001), stat=\'density\', ax=axs[0])\naxs[0].set_title(\'Measuring in meters\')\naxs[0].containers[1][40].set_color(\'r\')\n\na *= 1000\nsns.histplot(a, bins=np.arange(-40, 40, 1), stat=\'density\', ax=axs[1])\naxs[1].set_title(\'Measuring in milimeters\')\naxs[1].containers[1][40].set_color(\'r\')\n\nplt.show()\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n

左边的图使用0.001米宽的箱。最高的垃圾箱(红色)大约40高。某个值落入该 bin 的概率为40*0.001 = 0.04

\n

右图使用完全相同的数据,但以毫米为单位。现在垃圾箱很1 mm宽。最高的垃圾箱大约0.04高。0.04由于 bin 宽度为 ,因此值落入该 bin 的概率也为1

\n

作为概率密度函数具有大于 1 的区域的分布示例,请参阅带有 的Pareto 分布\xce\xb1 = 3

\n

通过直接使用plt.hist返回 bin 边缘和高度的 ,可以轻松计算面积。

\n
np.random.seed(2023)\na = np.random.normal(0, 0.01, 100000)\nv = plt.hist(a, bins=np.arange(-0.04, 0.04, 0.001), density=True, ec=\'k\')\n\nleft = v[1][:-1]\nright = v[1][1:]\narea = (v[0] * (right-left)).sum()\n\nprint(f\'Area: {area}\')\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n
\n

sns.distplot已弃用

\n
import numpy as np\nfrom matplotlib import pyplot as plt\nimport seaborn as sns\n\nfig, axs = plt.subplots(ncols=2, figsize=(14, 3))\n\na = np.random.normal(0, 0.01, 100000)\nsns.distplot(a, bins=np.arange(-0.04, 0.04, 0.001), ax=axs[0])\naxs[0].set_title(\'Measuring in meters\')\naxs[0].containers[0][40].set_color(\'r\')\n\na *= 1000\nsns.distplot(a, bins=np.arange(-40, 40, 1), ax=axs[1])\naxs[1].set_title(\'Measuring in milimeters\')\naxs[1].containers[0][40].set_color(\'r\')\n\nplt.show()\n
Run Code Online (Sandbox Code Playgroud)\n

演示图

\n