多个数据直方图的条形高度和宽度

2 投票
1 回答
10634 浏览
提问于 2025-04-18 04:16

我正在尝试绘制一个简单的直方图,想把多个数据并排显示。
我的数据是一组二维的ndarrays,它们的尺寸都是一样的(在这个例子中是256 x 256)。

我有一个方法来绘制这个数据集:

def plot_data_histograms(data, bins, color, label, file_path):
        """
        Plot multiple data histograms in parallel
        :param data : a set of data to be plotted
        :param bins : the number of bins to be used
        :param color : teh color of each data in the set
        :param label : the label of each color in the set
        :param file_path : the path where the output will be save
        """
        plt.figure()
        plt.hist(data, bins, normed=1, color=color, label=label, alpha=0.75)
        plt.legend(loc='upper right')
        plt.savefig(file_path + '.png')
        plt.close() 

我这样传递我的数据:

data = [sobel.flatten(), prewitt.flatten(), roberts.flatten(), scharr.flatten()]
labels = ['Sobel', 'Prewitt', 'Roberts Cross', 'Scharr']
colors = ['green', 'blue', 'yellow', 'red']

plot_data_histograms(data, 5, colors, labels, '../Visualizations/StatisticalMeasures/RMSEHistograms')

然后我得到了这个直方图:

histogram

我知道这可能听起来有点傻,但我不明白为什么我的yticks会从0变到4.5。我知道这是因为normed参数,但即使我读了这个;

如果 True,返回的元组的第一个元素将是经过归一化的计数,形成一个概率密度,也就是说,n/(len(x)*dbin)。在概率密度中,直方图的积分应该是1;你可以通过对概率密度函数进行梯形积分来验证这一点。

我真的不明白这是怎么回事。

另外,当我把我的bins设置为5时,直方图正好有5个xticks(不包括边界),我不明白为什么有些条形图会出现在某些刻度的中间,比如在0.6刻度上方的黄色条。因为我的bins数量和xticks数量是匹配的,我以为每组四个条形图应该集中在每个区间内,就像前四个条形图完全集中在[0.0, 0.2]区间内那样。

提前谢谢你。

1 个回答

2

这段内容让人困惑的原因是,你把四个直方图挤在了一张图上。为了做到这一点,matplotlib会把柱子的宽度缩小,并在它们之间留出空隙。在标准的直方图中,所有柱子的总面积要么是1(如果normed为真),要么是N。下面是一个简单的例子:

 a = np.random.rand(10)
 bins = np.array([0, 0.5, 1.0]) # just two bins
 plt.hist(a, bins, normed=True)

normed

首先注意,每个柱子覆盖了它所在区间的整个范围:第一个柱子的范围是从00.5,它的高度由这个范围内的数据点数量决定。
接下来,你可以看到这两个柱子的总面积是1,因为normed = True:每个柱子的宽度是0.5,而高度分别是1.20.8

现在我们用另一组数据再画一次同样的图,这样你可以看到效果:

 b = np.random.rand(10)
 plt.hist([a, b], bins, normed=True)

normed with two

记住,蓝色的柱子代表的正是第一张图中的相同数据,但现在它们的宽度不到一半,因为需要为绿色的柱子留出空间。你可以看到,现在两个柱子加上一些空白覆盖了每个区间的范围。所以在计算区间和柱子面积时,我们必须假装每个柱子的宽度实际上是所有柱子的宽度加上空白间隙的宽度。

最后,注意到x轴的刻度并没有和柱子的边缘对齐。如果你希望这样,可以手动设置:

plt.xticks(bins)

如果你没有先手动创建bins,可以从plt.hist中获取:

counts, bins, bars = plt.hist(...)
plt.xticks(bins)

撰写回答