如何绘制链接多个seaborn小提琴分布中值的线?

时间:2020-07-29 14:32:32

标签: matplotlib seaborn

要想在每种堆叠式小提琴分布的中值(以及最小值和最大值)之间绘制一条虚线,我会很努力。 我尝试将小提琴图与seaborn.lineplot叠加,但是失败了。我不确定是否可以绘制点线并链接相同类型的分布的最小值和最大值。我也尝试使用seaborn.lineplot,但是这里的挑战是绘制每个x轴值的最小和最大分布。

这是一个示例数据集,以及seaborn中的小提琴图的代码

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

x=[0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.4,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.6,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8]
cate=['a','a','a','a','b','b','b','b','c','c','c','c','a','a','a','a','b','b','b','b','c','c','c','c','a','a','a','a','b','b','b','b','c','c','c','c','a','a','a','a','b','b','b','b','c','c','c','c']
y=[1.1,1.12,1.13,1.13,3.1,3.12,3.13,3.13,5.1,5.12,5.13,5.13,2.2,2.22,2.25,2.23,4.2,4.22,4.25,4.23,6.2,6.22,6.25,6.23,2.2,2.22,2.24,2.23,4.2,4.22,4.24,4.23,6.2,6.22,6.24,6.23,1.1,1.13,1.14,1.12,3.1,3.13,3.14,3.12,5.1,5.13,5.14,5.12]

my_pal =['red','green', 'purple']

df = pd.DataFrame({'x': x, 'Type': cate, 'y': y})
ax=sns.catplot(y='y', x='x',data=df, hue='Type', palette=my_pal,  kind="violin",dodge =False) 
sns.lineplot(y='y', x='x',data=df, hue='Type', palette=my_pal,  ci=100,legend=False)
plt.show()

,但它仅在图左侧的缩小部分上绘制线。将线图与小提琴图叠加起来有技巧吗?

1 个答案:

答案 0 :(得分:1)

对于折线图,“ x”被视为数字。但是,对于小提琴图,“ x”被认为是分类的(位于0、1、2,...)。

一种解决方案是将“ x”转换为字符串,以使两个图都将其视为分类。

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

my_pal = ['red', 'green', 'purple']
N = 40
df = pd.DataFrame({'x': np.random.randint(1, 6, N*3) * 0.2,
                   'y': np.random.uniform(0, 1, N*3) + np.tile([2, 4, 6], N),
                   'Type': np.tile(list('abc'), N)})
df['x'] = [f'{x:.1f}' for x in df['x']]
ax = sns.violinplot(y='y', x='x', data=df, hue='Type', palette=my_pal, dodge=False)
ax = sns.lineplot(y='y', x='x', data=df, hue='Type', palette=my_pal, ci=100, legend=False, ax=ax)
ax.margins(0.15)  # slightly more padding for x and y axis
ax.legend(bbox_to_anchor=(1.01, 1), loc='upper left')
plt.tight_layout()
plt.show()

resulting plot