如何在Seaborn柱状图中为不同hue分组配置独立调色板
原生Seaborn的barplot的palette参数仅支持按hue类别统一分配颜色,不直接支持x和hue双维度的自定义配色,可通过以下两种方案实现需求:
最优方案:单次调用barplot实现
保留Seaborn原生分组错位逻辑,调用后手动修改柱子和误差棒颜色,同时自定义图例:
import seaborn as sns import matplotlib.pyplot as plt from matplotlib.patches import Patch data = sns.load_dataset('attention') # 按柱子绘制顺序定义颜色:solutions=1的divided、focused → solutions=2的divided、focused... color_order = ["darkred", "red", "darkgreen", "green", "darkblue", "blue"] # 每个柱子对应1条误差竖线、2个端帽,共3个line对象,复制颜色顺序匹配 err_color_order = [c for c in color_order for _ in range(3)] sns.set(style='ticks', context='notebook', font_scale=1.2) fig, ax = plt.subplots(figsize=(7, 5), dpi=96) # 基础调用barplot,固定hue顺序保证柱子顺序和我们定义的颜色一致 sns.barplot( x="solutions", y="score", hue="attention", hue_order=["divided", "focused"], capsize=.1, ax=ax, data=data ) # 修改柱子填充色 for patch, color in zip(ax.patches, color_order): patch.set_facecolor(color) # 修改误差棒颜色 for line, color in zip(ax.lines, err_color_order): line.set_color(color) # 自定义符合需求的图例 legend_elements = [ Patch(facecolor='dimgray', label='divided'), Patch(facecolor='lightgray', label='focused') ] ax.legend(handles=legend_elements, title='attention') sns.despine(top=True, right=True) plt.tight_layout() plt.show()
次优方案:多次调用barplot实现
手动控制柱子偏移避免重叠,添加label参数自动生成图例:
import seaborn as sns import matplotlib.pyplot as plt import numpy as np data = sns.load_dataset('attention') bar_width = 0.35 # 单组柱子宽度,两组总宽度小于1保留间距 base_x = np.arange(3) # solutions三个取值的基准x坐标 sns.set(style='ticks', context='notebook', font_scale=1.5) fig, ax = plt.subplots(figsize=(7, 5), dpi=96) # 绘制divided分组,向左偏移半个宽度 sns.barplot( x=base_x - bar_width/2, y="score", palette=['darkred', 'darkgreen', 'darkblue'], capsize=.1, ax=ax, width=bar_width, data=data.query('attention=="divided"'), label='divided' ) # 绘制focused分组,向右偏移半个宽度 sns.barplot( x=base_x + bar_width/2, y="score", palette=['red', 'green', 'blue'], capsize=.1, ax=ax, width=bar_width, data=data.query('attention=="focused"'), label='focused' ) # 还原x轴标签为solutions取值 ax.set_xticks(base_x) ax.set_xticklabels([1,2,3]) ax.set_xlabel('solutions') ax.legend(title='attention') sns.despine(top=True, right=True) plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者TSeymour
相关产品推荐
相关产品推荐

