为什么 matplotlib 绘图和 seaborn 绘图中的计数值不同,而且都是错误的?

Why are the value of counts in the matplotlib plot and seaborn plot different, and both wrong?

所以我使用的数据集是来自 seaborntips。 我想针对 total_bill 列绘制直方图,我同时使用了 seaborn 和 matlotlib。

这是我的 matplotlib 直方图:

plt.hist(tips_df.total_bill);

这是我的 seaborn 直方图:

sns.histplot(tips_df.total_bill)

如您所见,在 total_bill 13 附近,频率似乎是最大的。 但是,在 matplotlib 中它大约是 68,而它在 seaborn 中大约是 48。

两者都是错误的。因为打字

tips_df["total_bill"].value_counts().sort_values(ascending=False).head(5)

我们得到输出

13.42    3
15.69    2
10.34    2
10.07    2
20.69    2

Name: total_bill, dtype: int64

我们可以看到,出现次数最多的是13左右,但是为什么y-axis上的计数值不对呢?

在直方图中,“矩形”的高度表示给定 范围 中有多少个值,而这又由矩形的宽度描述。您可以通过 (max - min) / number_of_rectangles.

得到每个矩形的宽度

例如,在 matplotlib 的输出中,有 10 个矩形(箱)。由于您的数据最小值约为 3,最大值约为 50,因此每个宽度约为 4.7 个单位宽。现在,为了获得第三个矩形范围,例如,我们从最小值开始并添加此宽度直到我们到达那里,即 3 + 4.7*2 = 12.4。然后它结束于 12.4 + 4.7 = 17.1。因此,对应于 3rd bin 的计数是 tips_df.total_bill 中落入该范围内的值的数量。让我们手动找到它:

>>> tips_df.total_bill.between(12.4, 17.1).sum()
70

(由于我在计算范围时使用了粗略的近似值并省略了精度,所以它并不准确;但我希望你能感觉到。)

到目前为止,这是为了解释为什么直接 value_counts 不直接匹配直方图输出,因为它给出逐值计数,而直方图大约是 范围s.

现在,为什么 seaborn 和 matplotlib 之间的图表不同?这是因为他们使用的垃圾箱数量不同!如果你算一下,matplotlib 有 10 个,seaborn 有 14 个。由于你没有为它们中的任何一个指定 bins 参数,它们使用默认值并且 matplotlib 默认为 plt.rcParams["hist.bins"] 并且 seaborn 选择“自动”(见注释 部分 here).

所以,我们不妨给出 bins 个参数来强制执行相同的输出:

>>> plt.hist(tips_df.total_bill, bins=10)

>>> sns.histplot(tips_df.total_bill, bins=10)