为什么当分布紧密聚集时,直方图显示不正确? [重复]

问题描述 投票:0回答:2

我试图在直方图中显示一些数据,但是当数据聚集得太紧密时,我要么得到一张空图,要么得到一个我认为不准确的图表。

考虑以下代码:

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中的空直方图 - 小间隔数据非常相似,但我认为我已经更明确地提出了问题,并注意到了一个额外的问题,即使结果图不是空白的(即最高值)我的第三个地块的较窄的垃圾箱比第二个地块的垃圾箱更大)

python matplotlib histogram dpi antialiasing
2个回答
0
投票

处理随机数据时,设置种子总是一个好主意,以保证每次运行都处理相同的数据。

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

如果数据相同但绘图不同,则这似乎是一个低分辨率问题。在这里你可以看到另外两张图片:

  • 这个之前有一个

    fig.set_size_inches(10, 5)
    plt.show

  • 这个之前有一个

    fig.set_size_inches(100, 50)
    plt.show

您可以在本地电脑上以更高的分辨率尝试此操作,但这实际上可以解决问题。

对于低分辨率的图形,要绘制的箱数多于正在使用的像素,因此

matplotlib
必须进行某种数据采样。这就是为什么每次放大或缩小绘图都会发生变化的原因。
如果您为绘图设置更大的大小,它将能够显示更多数量的垃圾箱,从而使您的绘图更值得信赖。


0
投票
  • 正如@RuthC在这个评论中所指出的:你的图像都是大约500像素宽。您正在丢失直方图的细节,因为您没有足够的像素来表示它。 x 轴限制越大,可用像素就越少,因此丢失的细节就越多。
    • 在 32 英寸 (2560 x 1440) 显示屏上,可以看到带有
      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

© www.soinside.com 2019 - 2024. All rights reserved.