如何在Seaborn中格式化/访问小提琴图catplot的内部箱线图?
问题

我正在使用Seaborn绘制kind为violin的catplot,希望修改其中小提琴图的内部箱线图格式。尝试使用violinplot的参数inner_kws=dict(box_width=15, whis_width=2, color=".8"),但未生效。
使用的代码
p = sns.catplot(data=sample4, x='modelID', y='error', hue='isDF', size=3, kind='violin', split=True, height=5, aspect=1.8, inner='box', fill=False, inner_kws=dict(box_width=15, whis_width=2, color=".8")) p.set(ylabel='occupancy error', title='Error distribution by model type for busy variable legs') p.set_xticklabels(rotation=45) for i,ax in enumerate(p.axes.flatten()): ax.axhline(0.2, ls='--', color='k', alpha=0.1, zorder=0) ax.axhline(-0.2, ls='--', color='k', alpha=0.1, zorder=0) ax.axhline(0, ls='--', color='k', alpha=0.3, zorder=0)
示例数据
modelID isDF error 622 MonthAverage No -0.182288 1096 S-AVG-1 No 0.122069 1277 S-AVG-4 No 0.105147 2189 NoChange Yes -0.189221 1250 S-AVG-4 No -0.037150 1530 GMM Yes 0.068475 1553 GMM Yes -0.543998 789 MonthAverage No -0.164985 1061 S-AVG-1 No 0.064435 1602 MonthAverage Yes -0.062130 448 GMM No 0.478873 1513 GMM Yes 0.166998 1349 S-AVG-4 No -0.069806 1860 GAM Yes 0.034769 830 NoChange No -0.150372 1151 S-AVG-1 No -0.142022 846 NoChange No -0.385930 1847 GAM Yes 0.102694 1049 S-AVG-1 No 0.095174 921 NoChange No -0.102451
解决方法
核心问题是inner_kws里的参数取值逻辑:box_width和whis_width是相对宽度(相对于小提琴图的宽度),不是绝对像素值。你设置的box_width=15过大,会导致箱线图超出小提琴范围,看起来像是参数未生效。
调整参数取值后即可生效,修改后的代码如下:
p = sns.catplot(data=sample4, x='modelID', y='error', hue='isDF', kind='violin', split=True, height=5, aspect=1.8, inner='box', fill=False, inner_kws=dict(box_width=0.3, whis_width=0.2, color=".8")) p.set(ylabel='occupancy error', title='Error distribution by model type for busy variable legs') p.set_xticklabels(rotation=45) for ax in p.axes.flatten(): ax.axhline(0.2, ls='--', color='k', alpha=0.1, zorder=0) ax.axhline(-0.2, ls='--', color='k', alpha=0.1, zorder=0) ax.axhline(0, ls='--', color='k', alpha=0.3, zorder=0)
如果你的Seaborn版本较旧(低于0.11),可能存在catplot传递inner_kws的兼容性问题,此时可以手动遍历轴元素修改样式:
import matplotlib.patches import matplotlib.lines p = sns.catplot(data=sample4, x='modelID', y='error', hue='isDF', kind='violin', split=True, height=5, aspect=1.8, inner='box', fill=False) p.set(ylabel='occupancy error', title='Error distribution by model type for busy variable legs') p.set_xticklabels(rotation=45) # 手动修改内部箱线图样式 for ax in p.axes.flatten(): for artist in ax.get_children(): # 修改箱体样式 if isinstance(artist, matplotlib.patches.Rectangle): artist.set_width(0.3) artist.set_color(".8") # 修改须的宽度 elif isinstance(artist, matplotlib.lines.Line2D) and artist.get_linewidth() == 1: artist.set_linewidth(2) # 添加水平线 ax.axhline(0.2, ls='--', color='k', alpha=0.1, zorder=0) ax.axhline(-0.2, ls='--', color='k', alpha=0.1, zorder=0) ax.axhline(0, ls='--', color='k', alpha=0.3, zorder=0)
内容的提问来源于stack exchange,提问作者ciaran haines
相关产品推荐
相关产品推荐

