绘制直方图,使直方图的总面积等于 1(密度)

Posted

技术标签:

【中文标题】绘制直方图,使直方图的总面积等于 1(密度)【英文标题】:Plot a histogram such that the total height equals 1 【发布时间】:2014-04-10 01:52:12 【问题描述】:

我正在尝试绘制标准化直方图,但不是将 1 作为 y 轴上的最大值,而是得到不同的数字。

对于数组 k=(1,4,3,1)

 import numpy as np

 def plotGraph():

    import matplotlib.pyplot as plt

    k=(1,4,3,1)

    plt.hist(k, normed=1)

    from numpy import *
    plt.xticks( arange(10) ) # 10 ticks on x axis

    plt.show()  

plotGraph()

我得到了这个直方图,它看起来不像规范的。

对于不同的数组 k=(3,3,3,3)

 import numpy as np

 def plotGraph():

    import matplotlib.pyplot as plt

    k=(3,3,3,3)

    plt.hist(k, normed=1)

    from numpy import *
    plt.xticks( arange(10) ) # 10 ticks on x axis

    plt.show()  

plotGraph()

我得到这个最大 y 值为 10 的直方图。

对于不同的 k,即使 normed=1 或 normed=True,我也会得到不同的 y 最大值。

为什么标准化(如果有效)会根据数据发生变化,如何使 y 的最大值等于 1?

更新:

我正在尝试实现来自plotting histograms whose bar heights sum to 1 in matplotlib 的Carsten König 答案并得到非常奇怪的结果:

import numpy as np

def plotGraph():

    import matplotlib.pyplot as plt

    k=(1,4,3,1)

    weights = np.ones_like(k)/len(k)
    plt.hist(k, weights=weights)

    from numpy import *
    plt.xticks( arange(10) ) # 10 ticks on x axis

    plt.show()  

plotGraph()

结果:

我做错了什么?

谢谢

【问题讨论】:

对于probability:Plot a histogram such that bar heights sum to 1 (probability) 【参考方案1】: 最简单的解决方案是使用seaborn.histplot,或seaborn.displotkind='hist',并指定stat='density' 密度:归一化,使得直方图的总面积等于 1 probability:或 proportion:标准化,使条形高度总和为 1 看到这个answer。 data:pandas.DataFramenumpy.ndarray、映射或序列 seabornmatplotlib 的高级 API python 3.8.12matplotlib 3.4.3seaborn 0.11.2中测试

进口和数据

import seaborn as sns
import matplotlib.pyplot as plt

# load data
df = sns.load_dataset('penguins')

sns.histplot

轴级图
# create figure and axes
fig, ax = plt.subplots(figsize=(6, 5))

p = sns.histplot(data=df, x='flipper_length_mm', stat='density', ax=ax)

sns.displot

人物级情节
p = sns.displot(data=df, x='flipper_length_mm', stat='density', height=4, aspect=1.5)

【讨论】:

【参考方案2】:

一种方法是自己获取概率,然后使用plt.bar 进行绘图:

In [91]: from collections import Counter
    ...: c=Counter(k)
    ...: print c
Counter(1: 2, 3: 1, 4: 1)

In [92]: plt.bar(c.keys(), c.values())
    ...: plt.show()

结果:

【讨论】:

【参考方案3】:

当你绘制一个归一化直方图时,不是高度总和为一,而是曲线下方的面积总和为一:

In [44]:

import matplotlib.pyplot as plt
k=(3,3,3,3)
x, bins, p=plt.hist(k, density=True)  # used to be normed=True in older versions
from numpy import *
plt.xticks( arange(10) ) # 10 ticks on x axis
plt.show()  
In [45]:

print bins
[ 2.5  2.6  2.7  2.8  2.9  3.   3.1  3.2  3.3  3.4  3.5]

在此示例中,bin 宽度为 0.1,曲线下方的面积之和为 1 (0.1*10)。

要使高度之和为 1,请在 plt.show() 之前添加以下内容:

for item in p:
    item.set_height(item.get_height()/sum(x))

【讨论】:

OP 可能只想知道如何绘制高度表示概率密度的条形 @zhangxaochen,我们知道概率密度函数也可以超过1。也许他只是想让高度加一,这是可以做到的,见编辑。 @CTZhu 是的,我只想让身高加一。谢谢 @CTZhu 我收到“未定义名称'bins'”错误。 normed 参数接受布尔值,所以它应该是normed=True,现在不推荐使用density=True【参考方案4】:

以上几行如何:

weights = np.ones_like(myarray)/float(len(myarray))
plt.hist(myarray, weights=weights)

当我有这样的堆叠直方图时应该工作吗?-

n, bins, patches = plt.hist([from6to10, from10to14, from14to18, from18to22,  from22to6],
label= ['06:00-10:00','10:00-14:00','14:00-18:00','18:00- 22:00','22:00-06:00'],
stacked=True,edgecolor='black', alpha=0.8, linewidth=0.5, range=(np.nanmin(ref1arr),
stacked=True,edgecolor='black', alpha=0.8, linewidth=0.5, range=(np.nanmin(ref1arr), np.nanmax(ref1arr)), bins=10)

【讨论】:

欢迎来到 SO。这似乎是作为答案发布的问题。请参阅***.com/help/mcve。【参考方案5】:

您可以使用here 概述的解决方案:

weights = np.ones_like(myarray)/float(len(myarray))
plt.hist(myarray, weights=weights)

【讨论】:

您可以在评论中提及此链接,而不是单独发布作为答案 有什么大的不同吗?我只是想传达信息。【参考方案6】:

一个规范的直方图被定义为每列的宽度和高度的乘积之和等于总数。这就是为什么你没有让你的最大值等于一。

但是,如果你仍然想强制它为 1,你可以通过以下方式使用 numpy 和 matplotlib.pyplot.bar

sample = np.random.normal(0,10,100)
#generate bins boundaries and heights
bin_height,bin_boundary = np.histogram(sample,bins=10)
#define width of each column
width = bin_boundary[1]-bin_boundary[0]
#standardize each column by dividing with the maximum height
bin_height = bin_height/float(max(bin_height))
#plot
plt.bar(bin_boundary[:-1],bin_height,width = width)
plt.show()

【讨论】:

以上是关于绘制直方图,使直方图的总面积等于 1(密度)的主要内容,如果未能解决你的问题,请参考以下文章

ggplot2 堆叠直方图 - 转换为密度图

如何计算密度直方图中的高度(它们的总和不等于 1)?

MATLAB如何将概率密度向量绘制到直方图上?

Pandas一行代码绘制25种美图

使用 ggplot2 沿平滑曲线绘制直方图或密度

如何绘制直方图的密度而非计数? (Matplotlib)