Seaborn - grouped bar plot with Bottom parameter

Viewed 774

I want to create a bar plot (vertical) using seaborn, each x axis label will have n (2 in the example) bars of different colors - but each bar will be floating - in other words it uses the matplotlib bar bottom parameter

this works without the bottom part as follows, but fails with it

import pandas as pd
import seaborn as sns

d = {'month':['202001','202002','202003','202001','202002','202003'],
     'range' : [0.94,4.47,0.97,4.70,0.98,1.23],
     'bottom' : [8.59,17.05,8.35,17.78,8.32,5.67],
     'group' : ['a','a','a','b','b','b']
}
df = pd.DataFrame(data=d)
sns.barplot(data=df,x = "month", y = "range",hue='group')

(Sorry I can't upload the picture for some reason, I think the service is blocked from my work, but the code will display it if run)

but when I add the bottom parameters it fails

sns.barplot(data=df,x = "month", y = "range",hue='group',bottom='bottom')

I appreciate the help, and perhaps an explanation of why it is failing, as logically it should work

The bars indicate a range of forecasts for a measure, and I want to show them as a rectangle

1 Answers

sns itself doesn't handle bottom, so it's passed to plt.bar. But plt.bar requires bottom to have the same shape/size with x and y which is not the case when data is passed by sns.

Let's try a work around with pandas plot function:

to_plot = df.pivot(index='month',columns='group')

fig,ax = plt.subplots()
to_plot['range'].add(to_plot['bottom']).plot.bar(ax=ax)

# cover the bars up to `bottom`
# replace `w` with background color of your choice
to_plot['bottom'].plot.bar(ax=ax, color='w', legend=None)

Output:

enter image description here

sns.set() to_plot = df.pivot(index='month',columns='group')

For another approach that allows a specific style:

# set sns plot style
sns.set()

fig,ax = plt.subplots()
for i,(label,r) in enumerate(to_plot.iterrows()):
    plt.bar([i-0.1,i+0.1],r['range'],
            bottom=r['bottom'], 
            color=['C0','C1'],
            width=0.2)
    
plt.xticks(np.arange(len(to_plot)), to_plot.index);

Output:

enter image description here

Related