How to add percentages on top of bars in seaborn?

collarblind picture collarblind · Jul 31, 2015 · Viewed 46k times · Source

Given the following count plot how do I place percentages on top of the bars?

import seaborn as sns
sns.set(style="darkgrid")
titanic = sns.load_dataset("titanic")
ax = sns.countplot(x="class", hue="who", data=titanic)

enter image description here

For example for "First" I want total First men/total First, total First women/total First, and total First children/total First on top of their respective bars.

Please let me know if my explanation is not clear.

Thanks!

Answer

cphlewis picture cphlewis · Jul 31, 2015

sns.barplot doesn't explicitly return the barplot values the way matplotlib.pyplot.bar does (see last para), but if you've plotted nothing else you can risk assuming that all the patches in the axes are your values. Then you can use the sub-totals that the barplot function has calculated for you:

from matplotlib.pyplot import show
import seaborn as sns
sns.set(style="darkgrid")
titanic = sns.load_dataset("titanic")
total = float(len(titanic)) # one person per row 
#ax = sns.barplot(x="class", hue="who", data=titanic)
ax = sns.countplot(x="class", hue="who", data=titanic) # for Seaborn version 0.7 and more
for p in ax.patches:
    height = p.get_height()
    ax.text(p.get_x()+p.get_width()/2.,
            height + 3,
            '{:1.2f}'.format(height/total),
            ha="center") 
show()

produces

Countplot

An alternate approach is to do the sub-summing explicitly, e.g. with the excellent pandas, and plot with matplotlib, and also do the styling yourself. (Though you can get quite a lot of styling from sns context even when using matplotlib plotting functions. Try it out -- )