如何在Matplotlib柱状图中对qcut生成的分类X轴排序
解决pd.qcut分桶后Matplotlib柱状图X轴标签顺序错乱及ConversionError问题
问题场景
用pd.qcut将数据集的List Price Value字段划分为8个分位数桶,自定义标签如下:['0 - 7.99', '8 - 8.99', '9 - 9.99', '10 - 10.99', '11 - 12.99', '13 - 14.99', '15 - 16.99', '17+']
绘制归一化计数柱状图时出现两个问题:
- X轴刻度无法按自定义标签的顺序排列
- 手动设置
plt.xticks的ticks和标签时触发ConversionError:ConversionError: Failed to convert value(s) to axis units: ['0 - 7.99', '8 - 8.99', '9 - 9.99', '10 - 10.99', '11 - 12.99', '13 - 14.99', '15 - 16.99', '17+']
分桶代码:
JNF_prices_pb['List Price Bins'] = pd.qcut(JNF_prices_pb['List Price Value'], labels = ['0 - 7.99', '8 - 8.99', '9 - 9.99', '10 - 10.99', '11 - 12.99', '13 - 14.99', '15 - 16.99', '17+'], q = 8, precision = 0)
错误原因
value_counts()默认按计数从高到低排序,会打乱pd.qcut生成的分类标签的原始顺序plt.xticks的ticks参数需要传入数值型的刻度位置(如0、1、2...),直接传入字符串标签会触发类型转换错误
解决方法
方法一:保留分类原始顺序(最简单)
利用pd.Categorical的自带顺序,在value_counts()中添加sort=False参数,禁止按计数排序,绘图时会自动沿用自定义标签的顺序:
plt.figure(figsize=(8,5)) # 关键:sort=False 保留分类标签的原始顺序 JNF_prices_pb['List Price Bins'].value_counts(normalize=True, sort=False).plot(kind='bar') plt.xticks(rotation=45, fontsize=14) plt.yticks(fontsize=14) plt.ylabel('% of Total', fontsize=14) plt.xlabel('List Price ($)', fontsize=14) plt.title('Juvenile Nonfiction -- General -- Paperback', fontsize=16, fontweight='bold') plt.tight_layout() # 防止X轴标签被截断 plt.show()
方法二:手动控制刻度位置和标签(更灵活)
先获取按分类顺序排序的计数结果,再给plt.xticks传入数值型的刻度位置和对应的标签:
plt.figure(figsize=(8,5)) # 按分类标签的原始顺序排序计数结果 counts = JNF_prices_pb['List Price Bins'].value_counts(normalize=True).sort_index() counts.plot(kind='bar') # ticks传入数值位置(0到7),labels传入分类标签 plt.xticks(ticks=range(len(counts.index)), labels=counts.index, rotation=45, fontsize=14) plt.yticks(fontsize=14) plt.ylabel('% of Total', fontsize=14) plt.xlabel('List Price ($)', fontsize=14) plt.title('Juvenile Nonfiction -- General -- Paperback', fontsize=16, fontweight='bold') plt.tight_layout() plt.show()
额外注意
如果List Price Bins不是分类类型(可通过JNF_prices_pb['List Price Bins'].dtype查看),可以手动转换为有序分类:
JNF_prices_pb['List Price Bins'] = pd.Categorical( JNF_prices_pb['List Price Bins'], categories=['0 - 7.99', '8 - 8.99', '9 - 9.99', '10 - 10.99', '11 - 12.99', '13 - 14.99', '15 - 16.99', '17+'], ordered=True )
内容的提问来源于stack exchange,提问作者Michial Miller
相关产品推荐
相关产品推荐

