绘制按固定参数归一化的直方图

0 投票
2 回答
779 浏览
提问于 2025-04-18 13:06

我想用 histtype='step' 的样式来画一个 归一化 的直方图(这里的 归一化 是指把数据除以一个固定的值)。

问题是 plot.bar() 似乎不支持这种样式,而如果我用 plot.hist(),它是支持的,但我不知道怎么才能画出 归一化 的直方图。

下面是我想表达的一个简单示例:

import matplotlib.pyplot as plt
import numpy as np

def rand_data():
    return np.random.uniform(low=10., high=20., size=(200,))

# Generate data.
x1 = rand_data()

# Define histogram params.
binwidth = 0.25
x_min, x_max = x1.min(), x1.max()
bin_n = np.arange(int(x_min), int(x_max + binwidth), binwidth)

# Obtain histogram.
hist1, edges1 = np.histogram(x1, bins=bin_n)
# Normalization parameter.
param = 5.

# Plot histogram normalized by the parameter defined above.
plt.ylim(0, 3)
plt.bar(edges1[:-1], hist1 / param, width=binwidth, color='none', edgecolor='r')
plt.show()

(注意归一化:hist1 / param),这会生成这个结果:

enter image description here

我可以用以下代码生成一个 histtype='step' 的直方图:

plt.hist(x1, bins=bin_n, histtype='step', color='r')

然后得到:

enter image description here

但这样的话,它就没有按照 param 的值进行 归一化

2 个回答

1

这个步骤图会根据一组区间和这些区间里的数量(或者归一化的数量)来生成你想要的效果。在这里,我使用了plt.hist来获取数量,然后把它们画出来,并且进行了归一化处理。为了让图上有一条线,必须重复第一个数据点。

(a,b,c) = plt.hist(x1, bins=bin_n, histtype='step', color='r')
a = np.append(a[0],a[:])
plt.close()
step(b,a/param,color='r')

这样做还不太对,因为图的结尾没有正确处理,线的末端悬在空中,而不是直接落到x轴上。

你可以通过在'a'的末尾加一个0,以及在'b'中再加一个区间点来解决这个问题。

a=np.append(a[:],0)
b=np.append(b,(2*b[-1]-b[-2]))
step(b,a/param,color='r')

最后提到的ax.step会在你使用

fig, ax = plt.subplots()

时用到,这样你就可以直接访问图形和坐标轴。想要更多例子,可以查看 http://matplotlib.org/examples/ticks_and_spines/spines_demo_bounds.html

0

根据tcaswell的评论(使用 step),我自己写了一个答案。注意,我需要在 x 数组的开头添加一个零元素,同时在 y 数组的开头和结尾各添加一个零元素,这样 step 才能在柱子的开始和结束位置画出竖线。

下面是代码:

import matplotlib.pyplot as plt
import numpy as np

def rand_data():
    return np.random.uniform(low=10., high=20., size=(5000,))

# Generate data.
x1 = rand_data()

# Define histogram params.
binwidth = 0.25
x_min, x_max = x1.min(), x1.max()
bin_n = np.arange(int(x_min), int(x_max + binwidth), binwidth)

# Obtain histogram.
hist1, edges1 = np.histogram(x1, bins=bin_n)
# Normalization parameter.
param = 5.

# Create arrays adding elements so plt.bar will plot the first and last
# vertical bars.
x2 = np.concatenate((np.array([0.]), edges1))
y2 = np.concatenate((np.array([0.]), (hist1 / param), np.array([0.])))

# Plot histogram normalized by the parameter defined above.
plt.xlim(min(edges1) - (min(edges1) / 10.), max(edges1) + (min(edges1) / 10.))
plt.bar(x2, y2, width=binwidth, color='none', edgecolor='b')
plt.step(x2, y2, where='post', color='r', ls='--')

plt.show()

这是结果:

enter image description here

可以看到,step 生成的红线和 bar 生成的蓝线是一样的。

撰写回答