如何使用sharex = True在catplot(kind ='violin')的顶部对seaborn catplot(kind ='count')进行子图绘制

时间:2019-03-16 22:13:52

标签: python seaborn categorical-data

到目前为止,我已经尝试了以下代码:

# Import to handle plotting
import seaborn as sns

# Import pyplot, figures inline, set style, plot pairplot
import matplotlib.pyplot as plt

# Make the figure space
fig = plt.figure(figsize=(2,4))
gs = fig.add_gridspec(2, 4)
ax1 = fig.add_subplot(gs[0, :])
ax2 = fig.add_subplot(gs[1, :])

# Load the example car crash dataset
tips = sns.load_dataset("tips")

# Plot the frequency counts grouped by time
sns.catplot(x='sex', hue='smoker',
                                   kind='count',
                                   col='time',
                                   data=tips,
                                   ax=ax1)

# View the data
sns.catplot(x='sex', y='total_bill', hue='smoker',
                                                   kind='violin',
                                                   col='time',
                                                   split='True', 
                                                   cut=0, 
                                                   bw=0.25, 
                                                   scale='area',
                                                   scale_hue=False,
                                                   inner='quartile',
                                                   data=tips,
                                                   ax=ax2)

plt.close(2)
plt.close(3)
plt.show()

这似乎将每种分类图分别堆叠在彼此之上。 This seems to stack the categorial plots, of each kind respectively, on top of eachother.

我想要的是以下代码在单个图中的生成图,其中第一行的计数图和第二行的小提琴图。

# Import to handle plotting
import seaborn as sns

# Import pyplot, figures inline, set style, plot pairplot
import matplotlib.pyplot as plt

# Load the example car crash dataset
tips = sns.load_dataset("tips")

# Plot the frequency counts grouped by time
sns.catplot(x='sex', hue='smoker',
                                   kind='count',
                                   col='time',
                                   data=tips)

# View the data
sns.catplot(x='sex', y='total_bill', hue='smoker',
                                                   kind='violin',
                                                   col='time',
                                                   split='True', 
                                                   cut=0, 
                                                   bw=0.25, 
                                                   scale='area',
                                                   scale_hue=False,
                                                   inner='quartile',
                                                   data=tips)

我想要跨越图的第一行的实际分类计数图,该图还包含分类小提琴图(参见图3):
The actual categorical countplot that I would like to span row one of a figure that also contains a categorical violin plot (Ref. Image 3)

我想要跨越图的第二行的实际分类小提琴图,其中还包含分类计数图(参见图2):
The actual categorical violin plot that I would like to span row two of a figure that also contains a categorical countplot (Ref. Image 2)

我尝试了以下代码,这些代码迫使图位于同一图中。不利的一面是图形/轴的子项没有转移,即轴标签,图例和网格线。我对这种骇客感到很亲密,但需要其他推动或灵感来源。而且,我不再能够关闭旧的/不需要的数字。

# Import to handle plotting
import seaborn as sns

# Import pyplot, figures inline, set style, plot pairplot
import matplotlib.pyplot as plt

# Set some style
sns.set_style("whitegrid")

# Load the example car crash dataset
tips = sns.load_dataset("tips")

# Plot the frequency counts grouped by time
a = sns.catplot(x='sex', hue='smoker',
                                       kind='count',
                                       col='time',
                                       data=tips)

numSubs_A = len(a.col_names)

for i in range(numSubs_A):
    for p in a.facet_axis(0,i).patches:
        a.facet_axis(0,i).annotate(str(p.get_height()), (p.get_x()+0.15, p.get_height()+0.1))

# View the data
b = sns.catplot(x='sex', y='total_bill', hue='smoker',
                                                       kind='violin',
                                                       col='time',
                                                       split='True', 
                                                       cut=0, 
                                                       bw=0.25, 
                                                       scale='area',
                                                       scale_hue=False,
                                                       inner='quartile',
                                                       data=tips)

numSubs_B = len(b.col_names)

# Subplots migration
f = plt.figure()
for i in range(numSubs_A):
    f._axstack.add(f._make_key(a.facet_axis(0,i)), a.facet_axis(0,i))
for i in range(numSubs_B):
    f._axstack.add(f._make_key(b.facet_axis(0,i)), b.facet_axis(0,i))

# Subplots size adjustment
f.axes[0].set_position([0,1,1,1])
f.axes[1].set_position([1,1,1,1])
f.axes[2].set_position([0,0,1,1])
f.axes[3].set_position([1,0,1,1])

This image shows the hack'd method of forcing both catplots onto a single plot, it shows the deficiency of my implementation in that the labels, legends, and other children aren't coming for the ride/transfer

2 个答案:

答案 0 :(得分:2)

通常不可能将几个原始图形级功能的输出组合到一个图形中。另请参阅(this questionthis issue。我曾经wrote a hack从外部将这些数字组合起来,但是它有几个缺点。如果适合您,请随意使用它。

但通常,请考虑手动创建所需的绘图。在这种情况下,它可能看起来像这样:

import seaborn as sns
import matplotlib.pyplot as plt
sns.set()

fig, axes = plt.subplots(2,2, figsize=(8,6), sharey="row", sharex="col")

tips = sns.load_dataset("tips")
order = tips["sex"].unique()
hue_order = tips["smoker"].unique()


for i, (n, grp) in enumerate(tips.groupby("time")):
    sns.countplot(x="sex", hue="smoker", data=grp, 
                  order=order, hue_order=hue_order, ax=axes[0,i])
    sns.violinplot(x='sex', y='total_bill', hue='smoker', data=grp,
                   order=order, hue_order=hue_order,
                   split='True', cut=0, bw=0.25, 
                   scale='area', scale_hue=False,  inner='quartile', 
                   ax=axes[1,i])
    axes[0,i].set_title(f"time = {n}")

axes[0,0].get_legend().remove()
axes[1,0].get_legend().remove()
axes[1,1].get_legend().remove()
plt.show()

enter image description here

答案 1 :(得分:0)

seaborn.catplot不接受“ ax”参数,因此您的第一个代码有问题。

看来,需要进行一些骇客操作才能实现您希望的x共享:

How to plot multiple Seaborn Jointplot in Subplot

这样,您可以节省时间和精力,只需从第二个代码中手动堆叠两个图形即可。