如何在不同的 x 刻度上绘制不同类型的 seaborn 图?

How can I plot different types of seaborn plots on different x ticks?

我想要使用相同的 y 轴但 x 坐标不同的多种类型的 seaborn 图(见下图)。

我尝试过以不同的方式指定 X 轴坐标,但似乎无法正常工作。

这是一个几乎可以工作的代码示例

x=[1,2,3,3,3,4,4,5,5,6] # first violin
y=[4,4,5,5,5,5,6] # second violin 
z=[5,5,6] # swarmplot over second violin


for data,label in [(x,'x'),(y,'y'),(z,'z')]:
    for i in data:
        c2v['value'].append(i)
        c2v['key'].append(label)
    

data=pd.DataFrame(c2v)
data.head()

print(data.loc[data.key=='z'])
fig,ax=plt.subplots(1,figsize=(5,5),dpi=200)
ax = sns.violinplot(data=data.loc[data.key.isin(['x','y'])], x='key', y='value',palette=['honeydew','lightgreen'])
sns.swarmplot(x=['swarmplot']*len(data), y=data['value'], order=ax.get_xticklabels() + ['swarmplot'], ax=ax)               #.loc[data.key=='z',:]
ax.set_xlabel('')

生成如下图像:

但是,它正在绘制与 x/y/z 关联的所有值,而不仅仅是 z。当我将 dataframe 切片到 swarmplot 中的 'z' 时,我得到一个错误:

sns.swarmplot(x=['swarmplot']*len(data), y=data.loc[data.key=='z',:]['value'], order=ax.get_xticklabels() + ['swarmplot'], ax=ax)               
KeyError: 'swarmplot'

有什么建议吗?

要在同一个 x-axis 上绘制第二个绘图,您可以使用 order= 给出现有刻度标签的列表,附加新标签。

这是一个例子:

import seaborn as sns

tips = sns.load_dataset('tips')
ax = sns.swarmplot(data=tips, x='day', y='total_bill')
sns.violinplot(x=['violin']*len(tips), y=tips['total_bill'], order=ax.get_xticklabels() + ['violin'], ax=ax)
ax.set_xlabel('')

新问题中代码的问题在于,swarmplot 的 x=y= 需要相同数量的元素。似乎 swarmplot 重置了 y 限制,所以我添加了一些代码来重新调整那些:

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

x = [1, 2, 3, 3, 3, 4, 4, 5, 5, 6]  # first violin
y = [4, 4, 5, 5, 5, 5, 6]  # second violin
z = [5, 5, 6]  # swarmplot over second violin

data = pd.DataFrame({'value': np.concatenate([x, y, z]),
                     'key': ['x'] * len(x) + ['y'] * len(y) + ['z'] * len(z)})
fig, ax = plt.subplots(1, figsize=(5, 5))
ax = sns.violinplot(data=data.loc[data.key.isin(['x', 'y'])], x='key', y='value', palette=['honeydew', 'lightgreen'])
ymin1, ymax1 = ax.get_ylim()
swarm_data = data.loc[data.key == 'z', :]['value']
sns.swarmplot(x=['swarmplot'] * len(swarm_data), y=swarm_data, order=ax.get_xticklabels() + ['swarmplot'], ax=ax)
ymin2, ymax2 = ax.get_ylim()
ax.set_ylim(min(ymin1, ymin2), max(ymax1, ymax2))
ax.set_xlabel('')
ax.set_xticks(np.arange(3))
ax.set_xticklabels(['x', 'y', 'swarmplot'])
plt.show()

您可以通过直接使用数据而不创建数据框来简化事情:

x = [1, 2, 3, 3, 3, 4, 4, 5, 5, 6]  # first violin
y = [4, 4, 5, 5, 5, 5, 6]  # second violin
z = [5, 5, 6]  # swarmplot over second violin

fig, ax = plt.subplots(1, figsize=(5, 5))
ax = sns.violinplot(x=['x']*len(x) + ['y']*len(y), y=x + y, palette=['honeydew', 'lightgreen'])
ymin1, ymax1 = ax.get_ylim()
sns.swarmplot(x=['swarmplot'] * len(z), y=z, order=ax.get_xticklabels() + ['swarmplot'], ax=ax)
ymin2, ymax2 = ax.get_ylim()
ax.set_ylim(min(ymin1, ymin2), max(ymax1, ymax2))
ax.set_xticks(np.arange(3))
ax.set_xticklabels(['x', 'y', 'swarmplot'])
plt.show()