- The guy who created Seaborn doesn't like stacked bar charts (but that link has a hack which uses Seaborn + Matplotlib to make them anyway).
- If you're willing to accept a grouped bar chart instead of a stacked one, following are two approaches
- Tested in
python 3.8.11
, pandas 1.3.2
, matplotlib 3.4.3
, seaborn 0.11.2
# first some sample data
import numpy as np
import pandas as pd
import seaborn as sns
N = 1000
np.random.seed(365)
mark = np.random.choice([True, False], N)
periods = np.random.choice(['BASELINE', 'WEEK 12', 'WEEK 24', 'WEEK 4'], N)
df = pd.DataFrame({'mark':mark,'period':periods})
ct = pd.crosstab(df.period, df.mark)
mark False True
period
BASELINE 124 126
WEEK 12 102 118
WEEK 24 118 133
WEEK 4 140 139
# now stack and reset
stacked = ct.stack().reset_index().rename(columns={0:'value'})
# plot grouped bar chart
p = sns.barplot(x=stacked.period, y=stacked.value, hue=stacked.mark, order=['BASELINE', 'WEEK 4', 'WEEK 12', 'WEEK 24'])
sns.move_legend(p, bbox_to_anchor=(1, 1.02), loc='upper left')
- The point of using
pandas.crosstab
is to get the counts per group, however this can be bypassed by passing the original dataframe, df
, to seaborn.countplot
ax = sns.countplot(data=df, x='period', hue='mark', order=['BASELINE', 'WEEK 4', 'WEEK 12', 'WEEK 24'])
sns.move_legend(ax, bbox_to_anchor=(1, 1.02), loc='upper left')
for c in ax.containers:
# set the bar label
ax.bar_label(c, label_type='center')