绘制直方图,使直方图的总面积等于 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.displot
和kind='hist'
,并指定stat='density'
密度:归一化,使得直方图的总面积等于 1
probability:或 proportion:标准化,使条形高度总和为 1
看到这个answer。
data
:pandas.DataFrame
、numpy.ndarray
、映射或序列
seaborn
是 matplotlib
的高级 API
在python 3.8.12
、matplotlib 3.4.3
、seaborn 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(密度)的主要内容,如果未能解决你的问题,请参考以下文章