难以将 xticks 与直方图 bin 的边缘对齐

Difficulty aligning xticks to edge of Histogram bin

我正在尝试以 3 小时为间隔使用直方图显示一天中所有时间的数据频率。因此,我使用 8 个箱子。

plt.style.use('seaborn-colorblind')

plt.figure(figsize=(10,5))
plt.hist(comments19['comment_hour'], bins = 8, alpha = 1, align='mid', edgecolor = 'white', label = '2019', density=True)
plt.title('2019 comments, 8 bins')
plt.xticks([0,3,6,9,12,15,18,21,24])
plt.xlabel('Hours of Day')
plt.ylabel('Relative Frequency')
plt.tight_layout()
plt.legend()
plt.show()

但是,如下图所示,刻度未与 bin 边缘对齐。

您可以执行以下任一操作:

plt.figure(figsize=(10,5))

# define the bin and pass to plt.hist
bins = [0,3,6,9,12,15,18,21,24]
plt.hist(comments19['comment_hour'], bins = bins, alpha = 1, align='mid', 

# remove this line
# plt.xticks([0,3,6,9,12,15,18,21,24])
edgecolor = 'white', label = '2019', density=True)
plt.title('2019 comments, 8 bins')
plt.xlabel('Hours of Day')
plt.ylabel('Relative Frequency')
plt.tight_layout()
plt.legend()
plt.show()

或者:

fig, ax = plt.subplots()

bins = np.arange(0,25,3)
comments19['comment_hour'].plot.hist(ax=ax,bins=bins)

# other plt format

如果设置bins=8,seaborn 将设置 9 个均匀分布的边界,从输入数组中的最低值 (0) 到最高值 (23),因此在 [0.0, 2.875, 5.75, 8.625, 11.5, 14.375, 17.25, 20.125, 23.0]。要在 0, 3, 6, ... 处获得 9 个边界,您需要明确设置它们。

import numpy as np
import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt

plt.style.use('seaborn-colorblind')

comments19 = pd.DataFrame({'comment_hour': np.random.randint(0, 24, 100)})

plt.figure(figsize=(10, 5))
plt.hist(comments19['comment_hour'], bins=np.arange(0, 25, 3), alpha=1, align='mid', edgecolor='white', label='2019',
         density=True)
plt.title('2019 comments, 8 bins')
plt.xticks(np.arange(0, 25, 3))
plt.xlabel('Hours of Day')
plt.ylabel('Relative Frequency')
plt.tight_layout()
plt.legend()
plt.show()

请注意,您的 density=True 表示直方图的总面积为 1。由于每个 bin 的宽度为 3 小时,因此所有 bin 高度的总和将为 0.33 而不是 1.00 如您所料。要真正获得具有相对频率的 y 轴,您可以通过将小时数除以 3 来使内部 bin 宽度 1。之后您可以将 x 轴重新标记为小时。

因此,可以进行以下更改以使所有 bin 总和为 100%:

from matplotlib.ticker import PercentFormatter

plt.hist(comments19['comment_hour'] / 3, bins=np.arange(9), alpha=1, align='mid', edgecolor='white', label='2019',
         density=True)
plt.xticks(np.arange(9), np.arange(0, 25, 3))
plt.gca().yaxis.set_major_formatter(PercentFormatter(1))