使用sns.countplot()绘制MNIST数据时如何添加柱状图数值标注?
搞定Seaborn Countplot标注不显示、绘图顺序及副Y轴命名问题
一、先解决柱子数值标注不显示的坑
你这代码逻辑其实没问题,为啥标注不出来?大概率是坐标定位的小细节没调对,还有可能是没在最后调用plt.show()渲染图像。我给你改了下代码,保证标注能正常显示:
import seaborn as sns import matplotlib.pyplot as plt import numpy as np # 假设Y_train是你的MNIST训练集标签 plt.figure(figsize=(12,5)) # 建议显式指定x参数,避免不同Seaborn版本的兼容问题 digit_count = sns.countplot(x=Y_train) plt.title('Distribution of digits') # 遍历每个柱子加标注 for d in digit_count.patches: # 把标注放在柱子正上方,计算水平居中位置 x_pos = d.get_x() + d.get_width() / 2 y_pos = d.get_height() # 添加标注,设置对齐方式让位置更美观 digit_count.annotate(f'{int(y_pos)}', # MNIST样本数是整数,直接显示更清楚 (x_pos, y_pos), ha='center', # 水平居中 va='bottom', # 标注紧贴柱子顶部 fontsize=10) plt.show() # 必须加这个,不然图像和标注都不会渲染出来!
关键调整点:
- 显式传
x=Y_train:有些Seaborn版本对隐式传参支持不好,显式指定更稳。 - 水平居中计算:原来的
d.get_x()+0.1是固定偏移,换成d.get_x()+d.get_width()/2能自动适配柱子宽度,保证标注在正上方。 - 对齐参数:
ha='center'和va='bottom'让标注位置更规整,不会歪歪扭扭。 - 格式调整:用
int(y_pos)直接显示整数,比百分比更贴合MNIST的样本数量场景。
二、绘图先于print输出?调整顺序就行
为啥绘图总比print先出来?因为Matplotlib的绘图渲染是异步的,而print是同步执行的。你只要把print语句放到plt.show()之前就行,或者在Jupyter环境里,确保print代码在绘图代码之后、plt.show()之前执行。比如:
# 先统计数量并打印 counts = np.bincount(Y_train) for digit, cnt in enumerate(counts): print(f"数字{digit}的样本数:{cnt}") # 再绘图 plt.figure(figsize=(12,5)) digit_count = sns.countplot(x=Y_train) plt.title('Distribution of digits') # ... 加标注的代码 ... plt.show()
要是用Jupyter Notebook,记得开头加%matplotlib inline,能保证图像和打印内容按顺序显示。
三、副Y轴怎么命名?一行代码的事
你用twinx()创建副Y轴后,直接调用set_ylabel()就能给它加名称啦。不过说实话,如果你只是想显示样本数量,完全没必要用副Y轴——上面的柱子标注已经够用了。要是确实需要副轴,给你个示例:
plt.figure(figsize=(12,5)) digit_count = sns.countplot(x=Y_train) plt.title('Distribution of digits') # 创建副Y轴 twin_table = digit_count.twinx() # 设置副Y轴刻度(根据你的需求调范围) twin_table.set_yticks(np.arange(0, 7000, 1000)) # 给副Y轴起名字 twin_table.set_ylabel('样本数量(副轴)', fontsize=12) # 加柱子标注 for d in digit_count.patches: x_pos = d.get_x() + d.get_width()/2 y_pos = d.get_height() digit_count.annotate(f'{int(y_pos)}', (x_pos, y_pos), ha='center', va='bottom') plt.show()
内容的提问来源于stack exchange,提问作者CIsForCookies
相关产品推荐
相关产品推荐

