如何为seaborn的kdeplot/displot各hue分组设置不同linestyle
如何为seaborn KDE图的hue分组设置不同线型
问题背景
我们在使用seaborn.kdeplot、或指定了kind='kde'的seaborn.displot时,原生的linestyle/ls参数仅支持传入统一的字符串,会应用到所有hue分组上,无法针对单个分组单独配置。
原示例代码
import seaborn as sns import matplotlib.pyplot as plt # 加载示例数据 iris = sns.load_dataset("iris") # 转换为长表格式 im = iris.melt(id_vars='species') # axes级接口,所有分组共用同一种线型 fig = plt.figure(figsize=(6, 5)) p1 = sns.kdeplot(data=im, x='value', hue='variable', fill=True, ls='-.') # figure级接口,所有分组共用同一种线型 p2 = sns.displot(kind='kde', data=im, x='value', hue='variable', fill=True, ls='-.')
原绘制效果所有分组线型均为-.,无法区分。
解决方案
seaborn未提供直接通过参数映射hue和线型的能力,我们可以在绘图完成后遍历绘图对象的线条属性,手动为每个分组赋值不同线型。
axes级接口(kdeplot)实现
import seaborn as sns import matplotlib.pyplot as plt iris = sns.load_dataset("iris") im = iris.melt(id_vars='species') fig = plt.figure(figsize=(6, 5)) p1 = sns.kdeplot(data=im, x='value', hue='variable', fill=True) # 自定义线型列表,长度与hue分组数一致 linestyles = ['-', '--', '-.', ':'] # 遍历所有KDE线条设置线型 for line, ls in zip(p1.lines, linestyles): line.set_linestyle(ls) # 可选:同步更新图例显示的线型 handles = p1.get_legend().legendHandles for handle, ls in zip(handles, linestyles): handle.set_linestyle(ls) plt.show()
figure级接口(displot)实现
import seaborn as sns import matplotlib.pyplot as plt iris = sns.load_dataset("iris") im = iris.melt(id_vars='species') p2 = sns.displot(kind='kde', data=im, x='value', hue='variable', fill=True) linestyles = ['-', '--', '-.', ':'] # displot为FacetGrid对象,需先遍历获取所有子图axes for ax in p2.axes.flat: for line, ls in zip(ax.lines, linestyles): line.set_linestyle(ls) # 同步更新图例 handles = ax.get_legend().legendHandles for handle, ls in zip(handles, linestyles): handle.set_linestyle(ls) plt.show()
注意事项
- 自定义线型列表的长度需要和hue分组的数量完全匹配,避免出现赋值遗漏
- 若未开启fill填充,修改线条线型的逻辑同样生效
- 支持的matplotlib线型包括:
-(实线)、--(虚线)、-.(点划线)、:(点线)、None(隐藏)等
内容的提问来源于stack exchange,提问作者Trenton McKinney
相关产品推荐
相关产品推荐

