如何根据另外两行数据设置Seaborn柱状图的颜色
问题
我有如下pandas数据框:
index = ['Col-45', 'Col-68', 'Col-17', 'Col-69', 'Col-43', 'Col-49', 'Col-91', 'Col-13', 'Col-14', 'Col-18', 'Col-38', 'Col-37', 'Col-40', 'Col-44', 'Col-32', 'Col-82', 'Col-75', 'Col-19', 'Col-5', 'Col-6', 'Col-16', 'Col-4', 'Col-7', 'Col-41', 'Col-10', 'Col-31', 'Col-12', 'Col-11', 'Col-42', 'Col-30', 'Col-76', 'Col-46', 'Col-83', 'Col-73', 'Col-63', 'Col-9', 'Col-28', 'Col-51', 'Col-74', 'Col-65', 'Col-50', 'Col-64', 'Col-86', 'Col-79', 'Col-80', 'Col-81', 'Col-55', 'Col-1', 'Col-57', 'Col-2', 'Col-61', 'Col-53', 'Col-88', 'Col-47', 'Col-3', 'Col-58', 'Col-29', 'Col-59', 'Col-8', 'Col-276', 'Col-56', 'Col-62', 'Col-52', 'Col-54'] Brand = ['LG','LG','LG','LG','LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'Vivo', 'Vivo', 'Vivo', 'Vivo', 'Vivo', 'Vivo', 'Vivo', 'Sony', 'Sony', 'Sony', 'Sony', 'Sony', 'Sony', 'Sony', 'Pixel', 'Pixel', 'Pixel', 'Pixel', 'Huawei', 'Huawei', 'Huawei', 'Apple', 'Apple', 'Apple', 'Xiaomi', 'Xiaomi', 'Xiaomi', 'Lenovo', 'Lenovo', 'Lenovo', 'Panasonic', 'Panasonic', 'Panasonic', 'Beetle', 'Beetle', 'Samsung', 'Samsung', 'Nothing', 'Nothing', 'Nikon', 'Nikon', 'Canon', 'Canon', 'Coby', 'Coby', 'Onida', 'Amara', 'Roxy'] Score = [4.75, 0.91, 0.79, 0.65, 0.62, 0.57, 0.38, 0.33, 0.27, 0.25, 0.25, 0.22, 0.16, 0.11, 0.02, 0.01, 3.89, 3.08, 2.1 , 1.75, 0.42, 0.27, 0.18, 4.44, 1.18, 0.8 , 0.74, 0.52, 0.25, 0.08, 1.13, 0.75, 0.54, 0.04, 1.03, 0.11, 0. , 5.53, 5.24, 4.98, 0.98, 0.78, 0.06, 0.76, 0.28, 0.04, 1.1 , 0.38, 0.25, 0.98, 0.01, 1.17, 0.61, 0.29, 0.19, 0.12, 0.01, 0.13, 0. , 4.37, 3.59, 0.53, 0.39, 1.3 ] Choice = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0] Result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0] df = pd.DataFrame({'index':index,'Brand':Brand,'Score':Score,'Choice':Choice,'Result':Result}).set_index('index').T
我用以下代码绘制了Score行的Seaborn柱状图:
fig = plt.figure() sns.set(rc={'figure.figsize': (15,4)}) g1 = sns.barplot(data=df.loc[['Score']],color='blue') g1.patch.set_edgecolor('black') g1.patch.set_linewidth(0.5) g1.set_facecolor('white') g1.set_ylabel(f'Brand',weight='bold',fontsize=15) g1.set_xlabel(None) g1.set_xticklabels(g1.get_xticklabels(),rotation=90,fontsize=10) plt.show()
现在需要根据Choice和Result的取值修改柱子颜色,规则如下:
- Choice=0且Result=0:蓝色
- Choice=1且Result=0:绿色
- Choice=0且Result=1:粉色
- Choice=1且Result=1:红色
解决方案
核心思路是先根据Choice和Result的组合生成对应颜色列表,再逐个为柱子设置颜色,具体实现代码如下:
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # 数据准备(与原数据一致) index = ['Col-45', 'Col-68', 'Col-17', 'Col-69', 'Col-43', 'Col-49', 'Col-91', 'Col-13', 'Col-14', 'Col-18', 'Col-38', 'Col-37', 'Col-40', 'Col-44', 'Col-32', 'Col-82', 'Col-75', 'Col-19', 'Col-5', 'Col-6', 'Col-16', 'Col-4', 'Col-7', 'Col-41', 'Col-10', 'Col-31', 'Col-12', 'Col-11', 'Col-42', 'Col-30', 'Col-76', 'Col-46', 'Col-83', 'Col-73', 'Col-63', 'Col-9', 'Col-28', 'Col-51', 'Col-74', 'Col-65', 'Col-50', 'Col-64', 'Col-86', 'Col-79', 'Col-80', 'Col-81', 'Col-55', 'Col-1', 'Col-57', 'Col-2', 'Col-61', 'Col-53', 'Col-88', 'Col-47', 'Col-3', 'Col-58', 'Col-29', 'Col-59', 'Col-8', 'Col-276', 'Col-56', 'Col-62', 'Col-52', 'Col-54'] Brand = ['LG','LG','LG','LG','LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'LG', 'Vivo', 'Vivo', 'Vivo', 'Vivo', 'Vivo', 'Vivo', 'Vivo', 'Sony', 'Sony', 'Sony', 'Sony', 'Sony', 'Sony', 'Sony', 'Pixel', 'Pixel', 'Pixel', 'Pixel', 'Huawei', 'Huawei', 'Huawei', 'Apple', 'Apple', 'Apple', 'Xiaomi', 'Xiaomi', 'Xiaomi', 'Lenovo', 'Lenovo', 'Lenovo', 'Panasonic', 'Panasonic', 'Panasonic', 'Beetle', 'Beetle', 'Samsung', 'Samsung', 'Nothing', 'Nothing', 'Nikon', 'Nikon', 'Canon', 'Canon', 'Coby', 'Coby', 'Onida', 'Amara', 'Roxy'] Score = [4.75, 0.91, 0.79, 0.65, 0.62, 0.57, 0.38, 0.33, 0.27, 0.25, 0.25, 0.22, 0.16, 0.11, 0.02, 0.01, 3.89, 3.08, 2.1 , 1.75, 0.42, 0.27, 0.18, 4.44, 1.18, 0.8 , 0.74, 0.52, 0.25, 0.08, 1.13, 0.75, 0.54, 0.04, 1.03, 0.11, 0. , 5.53, 5.24, 4.98, 0.98, 0.78, 0.06, 0.76, 0.28, 0.04, 1.1 , 0.38, 0.25, 0.98, 0.01, 1.17, 0.61, 0.29, 0.19, 0.12, 0.01, 0.13, 0. , 4.37, 3.59, 0.53, 0.39, 1.3 ] Choice = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0] Result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0] df = pd.DataFrame({'index':index,'Brand':Brand,'Score':Score,'Choice':Choice,'Result':Result}).set_index('index').T # 定义颜色映射规则 color_map = { (0, 0): 'blue', (1, 0): 'green', (0, 1): 'pink', (1, 1): 'red' } # 生成每个柱子对应的颜色列表 colors = [color_map[(df.loc['Choice', col], df.loc['Result', col])] for col in df.columns] # 绘制柱状图并设置颜色 sns.set(rc={'figure.figsize': (15,4)}) fig, ax = plt.subplots() # 绘制基础柱状图,不指定统一颜色 g1 = sns.barplot(data=df.loc[['Score']], ax=ax) # 逐个为柱子设置颜色和边框样式 for bar, color in zip(g1.patches, colors): bar.set_color(color) bar.set_edgecolor('black') bar.set_linewidth(0.5) # 调整图表样式 ax.set_facecolor('white') ax.set_ylabel('Brand', weight='bold', fontsize=15) ax.set_xlabel(None) ax.set_xticklabels(ax.get_xticklabels(), rotation=90, fontsize=10) plt.show()
关键说明
- 用字典
color_map明确(Choice, Result)组合与颜色的对应关系,便于后续维护修改。 - 通过列表推导式生成颜色列表,确保颜色顺序与数据列完全匹配。
- 遍历
g1.patches获取每个柱子对象,逐个设置颜色和边框属性,保留原有的样式细节。
内容的提问来源于stack exchange,提问作者Yash
相关产品推荐
相关产品推荐

