0

I am trying to add the counts on top of a bar in Seaborn.

I tried it for one figure and it the following code worked.

fig, ax = plt.subplots(figsize=(20,10))

countplot_age = sns.countplot(ax=ax,x='Age', data=data4cap)

countplot_age.set_xticklabels(countplot_age.get_xticklabels(),rotation=90)

i=18

for p in countplot_age.patches:

    height = p.get_height()

    countplot_age.text(p.get_x()+p.get_width()/2, height + 0.1, data4cap['Age'].value_counts()[i],ha="center")
    i += 1
    
plt.show()

Countplot with values on top of bar

However, on the next plot, I am having issues because the X ticklabels returns in sequence 'Yes', 'No' while value_counts is returning - No 2466 and Yes 474.

[Return of unique values (also x-tick labels) and value_counts functions][2]

and using the same code, I am now getting the wrong value_counts on top of the bars.

fig,ax1 = plt.subplots(figsize = (15,10))

countplot_attrition = sns.countplot(data = data4cap, x = 'Attrition', ax= ax1)

countplot_attrition.set_xticklabels(countplot_attrition.get_xticklabels())

i=0

for p in countplot_attrition.patches:
    height = p.get_height()

    countplot_attrition.text(p.get_x()+p.get_width()/2, height + 0.1,
                             data4cap.Attrition.value_counts()[i], ha="center")

    i += 1
    
plt.show()

[Incorrect values on top of bars][3]

I was easily able to solve this by specifying the parameter of 'ascending' to True in value_counts, in THIS instance.

But that gets me wondering what if in some other instance there weren't only two values - and I had to map the ticklabels to value_counts somehow. The ticklabels return text object which is not subscriptable.

How would I do this?

Correct counts on top of bars, unique and value_count returns, incorrect counts on top of bars

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
RikkiS
  • 91
  • 1
  • 7
  • 1
    This [answer](https://stackoverflow.com/a/68323374/7758804) in the duplicate is the current way this should be accomplished. Update to `matplotlib 3.4.2` and then all you need after the plot is `countplot_attrition.bar_label(countplot_attrition.containers[0])`. – Trenton McKinney Aug 24 '21 at 23:55

1 Answers1

0

This error is caused by the fact that the order of the values to be annotated is different from the order obtained by value_counts(). So we can deal with it by aggregating the frequencies and reordering them by index. For the data, I used Titanic data to create the code.

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

sns.set_theme(style="darkgrid")

titanic = sns.load_dataset("titanic")

fig, ax1 = plt.subplots(figsize = (15,10))

countplot_attrition = sns.countplot(data=titanic, x='class', ax=ax1)
countplot_attrition.set_xticklabels(countplot_attrition.get_xticklabels())

for k,p in enumerate(countplot_attrition.patches):
    height = p.get_height()
    countplot_attrition.text(p.get_x()+p.get_width()/2, height + 0.1,
                             titanic['class'].value_counts().sort_index()[k], ha="center")

plt.show()

enter image description here

r-beginners
  • 31,170
  • 3
  • 14
  • 32