Pandas绘图图例与颜色映射问题求助
数据可视化问题解答
背景与代码
现有如下数据处理代码:
import numpy as np import pandas as pd # Data creation d1 = pd.DataFrame({ "Date": ['1/1/2022', '12/15/2010', '6/1/2015', '1/31/2022', '12/31/2010', '3/10/2009', '1/7/2022', '12/9/2010','12/20/2010','1/13/2022'], "Item": ['Food', 'Food', 'Gasoline', 'Coffee', 'Coffee', 'PayPal', 'Gasoline', 'Gasoline','Gasoline','Coffee'], "Price": [3.89, 7.00, 11, 0.99, 8.01, 99, 76, 50,48,9] }) # Change Date column to datetime d1['Date'] = pd.to_datetime(d1['Date']) # Create MMM-YY column from Date column d1['MMM-YY'] = d1['Date'].dt.strftime('%b') + '-' + d1['Date'].dt.strftime('%y') # Sort DataFrame by Date d1.sort_values('Date', inplace=True) # Group by MMM-YY, Item and sum Price d1_sorted = d1.groupby(['MMM-YY','Item'], sort = False)[['Price']].sum()
执行绘图代码:
d1_sorted.unstack().plot(kind = 'bar', title = 'Total Expense', stacked = True, figsize = (15,10), colormap = 'Blues')
得到堆叠条形图后,存在以下三个问题,对应解决方案如下:
问题与解决方案
1. 图例中出现“None,Item”项,是什么?如何移除?
原因:原代码中d1_sorted.unstack()生成的是多层索引(MultiIndex)列,第一层为Price,第二层为Item值。当部分MMM-YY分组下没有对应Item的数据时,会产生NaN值的列,绘图时因多层索引解析异常出现None项。
解决方法:调整groupby后的处理逻辑,直接生成单层索引的DataFrame,避免多层索引:
# 替换原groupby和unstack步骤 d1_sorted = d1.groupby(['MMM-YY','Item'], sort=False)['Price'].sum().unstack(fill_value=0) # 绘图 d1_sorted.plot(kind='bar', title='Total Expense', stacked=True, figsize=(15,10), colormap='Blues')
这样处理后,列名直接是Item的各个值,不会出现异常图例项。
2. 如何让图例仅显示Item列的值,而非(Price, PayPal)这类元组格式?
原因:原代码中unstack后的列是多层索引,图例默认显示完整的元组列名。
解决方法有两种:
- 方法一:提前避免多层索引(同问题1的解决方案),直接用单层索引列绘图,图例自动显示
Item值。 - 方法二:手动修改图例标签:
# 执行原绘图代码并获取轴对象 ax = d1_sorted.unstack().plot(kind='bar', title='Total Expense', stacked=True, figsize=(15,10), colormap='Blues') # 提取元组中的Item部分作为图例标签 handles, labels = ax.get_legend_handles_labels() ax.legend(handles, [label.split(', ')[1][:-1] for label in labels])
或者更简洁的方式,重命名多层索引列:
df_plot = d1_sorted.unstack() # 只保留第二层索引(Item值)作为列名 df_plot.columns = df_plot.columns.get_level_values(1) # 绘图 df_plot.plot(kind='bar', title='Total Expense', stacked=True, figsize=(15,10), colormap='Blues')
3. 调整Blues色卡让浅色变深,新手友好的非默认色卡推荐及颜色学习资源
调整Blues色卡的浅色
Matplotlib的Blues色卡是从浅到深的渐变,要跳过最浅的颜色,可以截取色卡的后半段区间:
import matplotlib.cm as cm # 获取Blues色卡,截取从0.2到1的区间(跳过前20%的浅色) blues_adjusted = cm.get_cmap('Blues')(np.linspace(0.2, 1, len(d1['Item'].unique()))) # 绘图时使用调整后的颜色 d1_sorted.plot(kind='bar', title='Total Expense', stacked=True, figsize=(15,10), color=blues_adjusted)
新手友好的非默认色卡推荐
- Seaborn系列:
'deep'(颜色饱满区分度高)、'pastel'(柔和不刺眼)、'dark'(深色系适合堆叠图) - Matplotlib定性色卡:
'tab10'(默认10色,清晰易记)、'tab20'(支持更多分类) - ColorBrewer系列:
'Set2'(柔和分类色)、'Paired'(成对颜色,适合对比场景)
颜色学习资源
- 核心原则:分类可视化用高区分度颜色,堆叠图用同色系渐变或亮度区分的互补色,避免红绿色盲难区分的组合;
- 直接查阅Matplotlib官方色卡示例,记住常用色卡的适用场景即可;
- Seaborn官方教程里有颜色搭配的详细指导,重点关注分类色、连续色的使用规范。
内容的提问来源于stack exchange,提问作者user603535
相关产品推荐
相关产品推荐

