How to overlay data points on a barplot with a categorical axis

4.6k Views Asked by At

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?

2

There are 2 best solutions below

0
On BEST ANSWER
  • 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

2
On
  • 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