我试图在直方图中显示一些数据,但是当数据聚集得太紧密时,我要么得到一张空图,要么得到一个我认为不准确的图表。
考虑以下代码:
import numpy as np
from matplotlib import pyplot as plt
# Generate data
nums = np.random.rand(1000)+1000
# Make Histogram
plt.hist(nums, bins=1000, alpha=0.6, color='blue')
plt.xlim([900,1100])
plt.yscale('linear')
plt.grid(True)
plt.show()
这给出了下图:
但是,如果我将 xlim 值更改为:
plt.xlim([990,1010])
我得到:
如果我再次更改它,
plt.xlim([999,1001])
我明白了
由于每个箱覆盖的数字范围较小,我预计箱的峰值会减少,而不是增加。有什么我不明白的地方吗,或者这是 matplotlib 的问题吗? (注意:这似乎与matplotlib中的空直方图 - 小间隔数据非常相似,但我认为我已经更明确地提出了问题,并注意到了一个额外的问题,即使结果图不是空白的(即最高值)我的第三个地块的较窄的垃圾箱比第二个地块的垃圾箱更大)
处理随机数据时,设置种子总是一个好主意,以保证每次运行都处理相同的数据。
import numpy as np
from matplotlib import pyplot as plt
# Generate data
np.random.seed(1000)
nums = np.random.rand(1000)+1000
即使使用完全相同的数据,我们也会面临您所说的相同问题。为了说明这一点,我将用四个不同的 x 轴限制来显示我的图:
fig, axs = plt.subplots(2, 2)
bins = 100
n0, bins0, patches0 = axs[0,0].hist(nums, bins=bins, color='blue')
axs[0,0].set_xlim([900,1100])
axs[0,0].grid()
n1, bins1, patches1 = axs[0,1].hist(nums, bins=bins, color='blue')
axs[0,1].set_xlim([990,1010])
axs[0,1].grid()
n2, bins2, patches2 = axs[1,0].hist(nums, bins=bins, color='blue')
axs[1,0].set_xlim([999,1002])
axs[1,0].grid()
n3, bins3, patches3 = axs[1,1].hist(nums, bins=bins, color='blue')
axs[1,1].set_xlim([999.9,1001.1])
axs[1,1].grid()
plt.show()
是的,即使有 100 个垃圾箱而不是 1000 个垃圾箱,问题也会出现。但是如果您检查
n
和 bins
中的信息,它们都是相同的(应该如此,因为情节完全相同).
可以通过执行来检查
print((n0 == n1).all() and (n0 == n2).all() and (n0 == n3).all())
# True
如果数据相同但绘图不同,则这似乎是一个低分辨率问题。在这里你可以看到另外两张图片:
您可以在本地电脑上以更高的分辨率尝试此操作,但这实际上可以解决问题。
对于低分辨率的图形,要绘制的箱数多于正在使用的像素,因此
matplotlib
必须进行某种数据采样。这就是为什么每次放大或缩小绘图都会发生变化的原因。xlim=[900, 1100]
的 100 dpi 直方图条。import numpy as np
import matplotlib.pyplot as plt
np.random.seed(20231117)
nums = np.random.rand(1000) + 1000
xlims = [[900, 1100], [990, 1010], [999, 1001]]
dpis = [100, 300, 600]
for dpi in dpis:
fig, axes = plt.subplots(1, 3, figsize=(20, 5), dpi=dpi)
axes = axes.flat
for ax, xlim in zip(axes, xlims):
ax.hist(nums, bins=1000, alpha=0.6, color='blue')
ax.set_xlim(xlim)
ax.set_yscale('linear')
ax.grid(True)
fig.savefig(f'00_{dpi}_test.png')
dpi=100
dpi=300
dpi=600