Pandas (grouped) barplot styling

Posted on fre 11 oktober 2019 in Programming

Styling of Pandas (grouped) barplot

I have been having problems to style barplots the way I would like to when plotting with Pandas. This is a very short post summarizing the things I have picked up.

In [1]:
import pandas as pd
%matplotlib inline

After the initial imports, we'll start with a simple plot.

In [2]:
testdata = pd.DataFrame({'x': [1, 3, 2, 4], 'y': [2, 5, 2, 3]})
In [3]:
testdata.plot.bar();

Som simple formatting to change series colors.

In [4]:
testdata.plot.bar(color=['#96ffff', '#3296ff'], edgecolor='black');

Error bars

Adding error bars is simple, but formatting them can be more troublesome. And finding the documentation was even more difficult. There are two simple keywords that can be used to style the bars, namely capsize and color of the bars.

In [5]:
testerr = pd.DataFrame({'x': [0.1, 1.3, 0.52, 1], 'y': [0.3, 0.5, 1.2, 3]})
testdata.plot.bar(color=['#96ffff', '#3296ff'], edgecolor='black', yerr=testerr);
In [6]:
testdata.plot.bar(color=['#96ffff', '#3296ff'], edgecolor='black', yerr=testerr, capsize=3)
Out[6]:
<matplotlib.axes._subplots.AxesSubplot at 0x233ed035358>
In [7]:
testdata.plot.bar(color=['#96ffff', '#3296ff'], edgecolor='black', yerr=testerr, capsize=3, ecolor='red')
Out[7]:
<matplotlib.axes._subplots.AxesSubplot at 0x233ed0b86a0>

After a lot of searching, I finally realized that the relevant docs are for matplotlib.pyplot.bar (I should probably have realized this sooner...) and there I found out about the error_kw dict where all arguments to matplotlib.pyplot.errorbar can be specified.

In [8]:
testdata.plot.bar(
    color=['#96ffff', '#3296ff'], edgecolor='black', yerr=testerr,
    error_kw={'capsize':3, 'ecolor':'red', 'elinewidth': 1, 'capthick': 3}
)
Out[8]:
<matplotlib.axes._subplots.AxesSubplot at 0x233ecf70cc0>

Spacing

There doesn't seem to be a way in Pandas to specify spacing in the grouped barplot. Instead I found this workaround:

In [9]:
import matplotlib

SPACING = 0.2
outplot = testdata.plot.bar(
    color=['#96ffff', '#3296ff'], edgecolor='black', yerr=testerr,
    error_kw={'capsize':3, 'ecolor':'red', 'elinewidth': 1, 'capthick': 3}
)
barplots = [c for c in outplot.containers if isinstance(c, matplotlib.container.BarContainer)]
barw = barplots[0].patches[0].get_width()
neww = barw * (1 - SPACING)
deltax = barw * SPACING / 2
for bars in barplots:
    for rect in bars:
        rect.set_width(neww)
        rect.set_x(rect.get_x() + deltax)

Conclusions

Above I presented a few tips on how to format a Pandas barplot. I hope it can help someone! If not, it will at least help the future me!