繁体   English   中英

如何使用 seaborn 在同一张图上绘制两个小提琴情节系列?

[英]How to plot two violin plot series on the same graph using seaborn?

查看有关seaborn的小提琴图的文档,我想知道如何在同一轴上绘制两个系列的小提琴图(第 1 点)并且它们具有可比性(第 2 点)。

关于第 1 点,我想为每种性别重现该情节:

fig, ax = plt.subplots()
sns.violinplot(x="day", y="total_bill", hue="smoker",
                    data=tips, split=True, ax=ax)

我可以在两个子图上做到这一点:

fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(211)
sns.violinplot(x="day", y="total_bill", hue="smoker",
               data=tips[tips.sex == "Female"], split=True, ax=ax)

ax = fig.add_subplot(212)
sns.violinplot(x="day", y="total_bill", hue="smoker",
               data=tips[tips.sex == "Male"], split=True, ax=ax)

我想在相同的 matplotlib 轴上绘制两个小提琴情节系列。

另一点是关于小提琴图的宽度。 我不清楚小提琴是否标准化以及如何标准化? 我假设为每个图计算宽度。 在上面的示例中,为第一个子图的女性和第二个子图的男性计算宽度。 因此我可以直接比较密度吗? 我想我可以比较形状,但是,例如,我不能比较周一男性吸烟者和女性吸烟者的数量? 有没有办法管理小提琴的正常化?

对于你的第一点,在Seaborn没有办法做到这一点。 查看我对可能的解决方法的评论,但简而言之,我认为花费的时间不值得。

对于你的第二个问题,在scalescale_hue参数violinplot控制小提琴补丁是如何标准化/缩放:

scale:{“area”,“count”,“width”},可选

用于缩放每个小提琴宽度的方法。 如果是区域,每个小提琴都会有相同的区域。 如果计数,小提琴的宽度将按照该箱中的观察次数进行缩放。 如果宽度,每个小提琴将具有相同的宽度。

scale_hue:bool,可选

当使用色调变量嵌套小提琴时,此参数确定是否在主要分组变量的每个级别(scale_hue = True)内或在绘图上的所有小提琴中计算缩放比例(scale_hue = False)。

默认值为'area'False 您可以在下面看到这些参数的变化如何影响小提琴。 例如,如果要比较绘图并真实地表示绝对计数,可以设置scale='count'scale_hue=False 请注意,小提琴仍然会缩放到图中的最大数量(而不是数据集中),所以在我们的例子中,女性最大的小提琴代表约40个观察,而男性最大的小提琴代表~25个观察。

fig, axes = plt.subplots(4, 2, figsize=(10, 16), sharey='row')
axes_cols = (axes.flatten()[::2], axes.flatten()[1::2])

for (sex_name, sex), axes_col in zip(tips.groupby('sex'), axes_cols):
    sns.countplot(x="day", hue="smoker", data=sex, ax=axes_col[0])
    for scale, ax in zip(['area', 'count', 'width'], axes_col[1:]):
        sns.violinplot(x="day", y="total_bill", hue="smoker",
            data=sex, split=True, ax=ax, scale=scale)
        ax.set_title('scale = {}'.format(scale), y=0.95)
sns.despine()
fig.tight_layout()

在此输入图像描述

添加scale_hue=False 在此输入图像描述

正如Joel Ostblom所说的那样,没有办法在seaborn中原生地绘制几个小提琴情节。 我建议按照他的提示解决这个问题。 我还在顶部添加了一个计数图,正如他在答案中所做的那样。

我真的不知道提示数据集,因此下面的情节肯定是没有意义的。

import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="whitegrid", font_scale=1.5)

tips = sns.load_dataset("tips")
# here you add a new column with the two categorical data you want
tips["sex_time"] = tips[["sex", "time"]].apply(lambda x: "_".join(x), axis=1)

fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(8, 10), 
                         sharex=True, gridspec_kw=dict(height_ratios=(1, 3), hspace=0))

# select the order you want:
order=["Female_Lunch", "Male_Lunch", "Female_Dinner", "Male_Dinner"]

sns.countplot(
    data=tips, x="sex_time", hue="smoker", 
    order=order,
    ax=axes[0]
)

sns.violinplot(
    x="sex_time", y="total_bill", hue="smoker", data=tips, 
    split=True, scale="count", scale_hue=False, inner="stick",
    order=order,
    ax=axes[1]
)
axes[1].set_xticklabels(["Lunch (Female)", "Lunch (Male)", "Dinner (Female)", "Dinner (Male)"])
axes[1].set_xlabel("Time (Sex)")
axes[1].legend("")

在此输入图像描述

为了补充@joelostblom 的答案,我想分享一个 DIY 解决方案,用于在同一轴上绘制两个系列的小提琴图。

import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

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

# Configure the coloring
color = {"Male": {"Yes": "orange", "No": "blue"}, "Female": {"Yes": "red", "No": "green"}}

# create figure and axes
fig, ax = plt.subplots()

# draw violins for each sex
sex_types = set(tips.sex)
for sex in sex_types:
    sns.violinplot(
        x="day", 
        y="total_bill", 
        hue="smoker",
        data=tips[tips.sex == sex],
        palette=color[sex],
        split=True,
        ax=ax,
        scale="count",
        scale_hue=False,
        saturation=0.75,
        inner=None
    )

# Set transparancy for all violins
for violin in ax.collections:
    violin.set_alpha(0.25)

# Compose a custom legend
custom_lines = [
    Line2D([0], [0], color=color[sex][smoker], lw=4, alpha=0.25) 
    for smoker in ["Yes", "No"] 
    for sex in sex_types
]
ax.legend(
    custom_lines, 
    [f"{sex} : {smoker}" for smoker in ["Yes", "No"] for sex in sex_types], 
    title="Gender : Smoker"
)

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM