3

Goal: I am trying to show individual data points in a figure with multiple grouped bar charts using Seaborn.

Problem: I tried to do it with a catplot for the bar chart and another catplot for the individual data points. However, this generates 2 figures: One figure with the bar chart and the other with the individual data points.

Question: Is there a way to show the individual data points in the same figure together with the bar chart using Seaborn?

This is my code generating 2 separate figures:

import seaborn as sns
tips = sns.load_dataset("tips")

g = sns.catplot(
    x="sex", 
    y="total_bill", 
    hue="smoker", 
    row="time", 
    data=tips, 
    kind="bar", 
    ci = "sd", 
    edgecolor="black",
    errcolor="black",
    errwidth=1.5,
    capsize = 0.1,
    height=4, 
    aspect=.7,
)

g = sns.catplot(
    x="sex", 
    y="total_bill", 
    hue="smoker", 
    row="time", 
    data=tips, 
    kind="strip", 
    height=4, 
    aspect=.7,
)

Output:

My output

Question: Is there a way to show the individual data points in the same figure together with the bar chart using Seaborn?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Alex Schubert
  • 67
  • 2
  • 7

2 Answers2

9
  • seaborn.catplot is a figure-level plot, and they can't be combined.
  • As shown below, axes-level plots like seaborn.barplot and seaborn.stripplot can be plotted to the same axes.
import seaborn as sns

tips = sns.load_dataset("tips")

ax = sns.barplot(
    x="sex", 
    y="total_bill", 
    hue="smoker", 
    data=tips, 
    ci="sd", 
    edgecolor="black",
    errcolor="black",
    errwidth=1.5,
    capsize = 0.1,
    alpha=0.5
)

sns.stripplot(
    x="sex", 
    y="total_bill", 
    hue="smoker", 
    data=tips, dodge=True, alpha=0.6, ax=ax
)

# remove extra legend handles
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles[2:], labels[2:], title='Smoker', bbox_to_anchor=(1, 1.02), loc='upper left')

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
r-beginners
  • 31,170
  • 3
  • 14
  • 32
  • Thanks! But how do you overlay data points on bar plots in a figure with multiple rows or columns, as stated in my code section _(row="time")_. Is there a way to do this? @Trenton McKinney – Alex Schubert Sep 30 '21 at 20:22
  • 1
    @AlexSchubert See [How to plot in multiple subplots](https://stackoverflow.com/a/69228859/7758804) for creating subplots with multiple rows and columns and then you would assign the barplot and stripplot to the same axes. – Trenton McKinney Sep 30 '21 at 20:40
4
  • Figure-level plots (seaborn.catplot) may not be combined, however, it's possible to map an axes-level plot (seaborn.stripplot) onto a figure-level plot.
  • palette=sns.color_palette()[:2] ensures the correct colors are used for the overlying markers, and [:2] selects the first two colors, which correspond to the colors use by hue='smoker'.
    • If a custom palette is specified for catplot, use it in .map.
  • Tested in python 3.11.2, matplotlib 3.7.1, seaborn 0.12.2
import seaborn as sns

tips = sns.load_dataset("tips")

g = sns.catplot(
    x="sex", 
    y="total_bill", 
    hue="smoker", 
    row="time", 
    data=tips, 
    kind="bar", 
    errorbar = "sd", 
    edgecolor="black",
    errcolor="black",
    errwidth=1.5,
    capsize = 0.1,
    height=4, 
    aspect=.7,
    alpha=0.5)

# map data to stripplot
g.map(sns.stripplot, 'sex', 'total_bill', 'smoker', hue_order=['Yes', 'No'], order=['Male', 'Female'],
      palette=sns.color_palette()[:2], dodge=True, alpha=0.6, ec='k', linewidth=1)

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158