簡體   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