Matplotlib水平柱状图正负值颜色统一异常问题求助
解决Matplotlib水平柱状图正负值颜色不区分问题
问题描述
尝试用Matplotlib绘制包含正负值的水平柱状图,期望负值柱子显示红色、正值显示青色,但只要数据集中存在负值,所有柱子都会变成红色,无法实现按值区分颜色。相关代码如下:
df = df.groupby('price').agg(quantity=('quantity','sum'), t_count=('price','size') ).dropna(how='any').sort_index(ascending=True) # example output of the groupby # quantity t_count bar_colors # price # 9.05 -10 2 red # 9.09 10 1 red # 9.15 -1304 6 red # 9.17 -91 2 red # 9.18 -202 1 red # 9.19 100 1 cyan # 9.25 1596 10 cyan plt.style.use('dark_background') plt.rcParams.update({'font.size': 12}) # set font size to 12 df['bar_colors'] = np.where(df['quantity'] < 0, 'red', 'cyan') ax = df.plot.barh(color=df['bar_colors']) # Add count as text to the end of each bar for i, (_, row)in enumerate(df.iterrows()): ax.text(row['quantity'] / 2, i, f"{row['t_count']}", ha='center', va='baseline', color='white') ax.set_xlabel('Quantity') ax.set_ylabel('Price') ax.legend(labels=[]) plt.show()
问题原因
pandas的DataFrame.plot.barh()方法中,color参数的作用是按数据列分配颜色,而非按单个柱子(行)分配。由于这里仅绘制quantity一列数据,color会直接取列表中的第一个颜色(红色),并将其应用到所有柱子上,忽略后续的颜色值。
解决方法
改用Matplotlib原生的barh()函数绘制,直接为每个柱子指定对应颜色,同时手动设置y轴刻度匹配price索引值。修改后的完整代码如下:
import matplotlib.pyplot as plt import numpy as np import pandas as pd # 数据预处理(保持原逻辑) df = df.groupby('price').agg( quantity=('quantity','sum'), t_count=('price','size') ).dropna(how='any').sort_index(ascending=True) plt.style.use('dark_background') plt.rcParams.update({'font.size': 12}) df['bar_colors'] = np.where(df['quantity'] < 0, 'red', 'cyan') # 改用Matplotlib原生API绘制柱状图 fig, ax = plt.subplots() y_positions = range(len(df)) # 为每个柱子指定对应颜色 ax.barh(y_positions, df['quantity'], color=df['bar_colors']) # 设置y轴刻度与标签,匹配price索引 ax.set_yticks(y_positions) ax.set_yticklabels(df.index) # 在柱子中间添加计数文本 for i, (_, row) in enumerate(df.iterrows()): # 根据值的正负调整文本位置,确保在柱子内部 x_pos = row['quantity'] / 2 ax.text(x_pos, i, f"{row['t_count']}", ha='center', va='center', color='white') ax.set_xlabel('Quantity') ax.set_ylabel('Price') ax.legend(labels=[]) plt.show()
说明
- 原生
barh()支持直接传入颜色列表,每个元素对应一个柱子的颜色,实现按值区分颜色的需求。 - 手动设置y轴刻度是因为原生API不会自动将DataFrame的索引作为y轴标签,需要显式指定。
- 将文本垂直对齐方式改为
va='center',让计数文本更居中显示在柱子内部。
内容的提问来源于stack exchange,提问作者John Holmes
相关产品推荐
相关产品推荐

