harnen
harnen

Reputation: 403

Seaborn Violin Plot - Apply hue and split options to different features

I'm trying to combine two Seaborn violin plots into a single one and display relations between three different features. I'm working on the tips dataset:

     total_bill   tip     sex smoker   day    time  size
0         16.99  1.01  Female     No   Sun  Dinner     2
1         10.34  1.66    Male     No   Sun  Dinner     3
2         21.01  3.50    Male     No   Sun  Dinner     3
3         23.68  3.31    Male     No   Sun  Dinner     2
4         24.59  3.61  Female     No   Sun  Dinner     4
..          ...   ...     ...    ...   ...     ...   ...
239       29.03  5.92    Male     No   Sat  Dinner     3
240       27.18  2.00  Female    Yes   Sat  Dinner     2
241       22.67  2.00    Male    Yes   Sat  Dinner     2
242       17.82  1.75    Male     No   Sat  Dinner     2
243       18.78  3.00  Female     No  Thur  Dinner     2

For this data set, I'd like to compare total_bill for different week days depending on sex and smoker columns using the split option. The graphs I'd like to combine are produced by the code below:

import seaborn as sns
import matplotlib.pyplot as plt

tips = sns.load_dataset("tips")
ax = sns.violinplot(x="day", y="total_bill", hue="smoker", data=tips, palette="muted", split=False)
ax = sns.violinplot(x="day", y="total_bill", hue="sex", data=tips, palette="muted", split=True)

enter code here enter image description here

Is it possible to create a single graph where different violins represent the total_bill distribution for smokers and non-smokers (as in the first graph), but each of violin is also split to represent differences between men and women? I'd still like to have 8 non-overlapping violins (2 per day - smokers and non smokers), but each will be further split between male and female.

I've found this thread, but the answer creates a separate violin for each combination which is not my goal.

Upvotes: 0

Views: 2003

Answers (1)

Smaurya
Smaurya

Reputation: 187

I believe this is what you are looking for

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
colors = {"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=colors[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=colors[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"
)

enter image description here

Upvotes: 2

Related Questions