'Display count on top of seaborn barplot
I have a dataframe that looks like:
User A B C
ABC 100 121 OPEN
BCD 200 255 CLOSE
BCD 500 134 OPEN
DEF 600 125 CLOSE
ABC 900 632 OPEN
ABC 150 875 CLOSE
DEF 690 146 OPEN
I am trying to display a countplot on column 'User'. The code is as follows:
fig, ax1 = plt.subplots(figsize=(20,10))
graph = sns.countplot(ax=ax1,x='User', data=df)
graph.set_xticklabels(graph.get_xticklabels(),rotation=90)
for p in graph.patches:
height = p.get_height()
graph.text(p.get_x()+p.get_width()/2., height + 0.1,
'Hello',ha="center")
The output looks like:
However, I want to replace string 'Hello' with the value_counts of column 'User'. When I add the code to add label to graph :
for p in graph.patches:
height = p.get_height()
graph.text(p.get_x()+p.get_width()/2., height + 0.1,
df['User'].value_counts(),ha="center")
I get the output as:
Solution 1:[1]
New in matplotlib 3.4.0
We can now automatically annotate bar plots with the built-in Axes.bar_label
, so all we need to do is access/extract the seaborn plot's Axes
.
Seaborn offers several ways to plot counts, each with slightly different count aggregation and Axes
handling:
seaborn.countplot
(most straightforward)This automatically aggregates counts and returns an
Axes
, so just directly labelax.containers[0]
:ax = sns.countplot(x='User', data=df) ax.bar_label(ax.containers[0])
seaborn.catplot
(kind='count'
)This plots a
countplot
onto a facet grid, so extract theAxes
from the grid before labelingax.containers[0]
:g = sns.catplot(x='User', kind='count', data=df) for ax in g.axes.flat: ax.bar_label(ax.containers[0])
seaborn.barplot
This returns an
Axes
but does not aggregate counts, so first computeSeries.value_counts
before labelingax.containers[0]
:counts = df['User'].value_counts().rename_axis('user').reset_index(name='count') ax = sns.barplot(x='user', y='count', data=counts) ax.bar_label(ax.containers[0])
If you are using hue
:
hue
plots will contain multiple bar containers, soax.containers
will need to be iterated:ax = sns.countplot(x='User', hue='C', data=df) for container in ax.containers: ax.bar_label(container)
Solution 2:[2]
df['User'].value_counts() will return a Series containing counts of unique values of the column User.
Without analyzing in much detail your code, you could correct it by indexing the result of value_counts with a counter:
fig, ax1 = plt.subplots(figsize=(20,10))
graph = sns.countplot(ax=ax1,x='User', data=df)
graph.set_xticklabels(graph.get_xticklabels(),rotation=90)
i=0
for p in graph.patches:
height = p.get_height()
graph.text(p.get_x()+p.get_width()/2., height + 0.1,
df['User'].value_counts()[i],ha="center")
i += 1
With your sample data, it produces the following plot:
As suggested by @ImportanceOfBeingErnest, the following code produces the same output with simpler code, using the height variable itself instead of the value_counts indexed:
fig, ax1 = plt.subplots(figsize=(20,10))
graph = sns.countplot(ax=ax1,x='User', data=df)
graph.set_xticklabels(graph.get_xticklabels(),rotation=90)
for p in graph.patches:
height = p.get_height()
graph.text(p.get_x()+p.get_width()/2., height + 0.1,height ,ha="center")
Solution 3:[3]
other solution
#data
labels=data['Sistema Operativo'].value_counts().index
values=data['Sistema Operativo'].value_counts().values
plt.figure(figsize = (15, 8))
ax = sns.barplot(x=labels, y=values)
for i, p in enumerate(ax.patches):
height = p.get_height()
ax.text(p.get_x()+p.get_width()/2., height + 0.1, values[i],ha="center")
Solution 4:[4]
Note: This solution does not try to show the count on top of the bar. Instead, this simple solution will print the values inside the bar. This may be an elegant solution for some occasions.
import seaborn as sns
ax=sns.countplot(x=df['category'], data=df);
for p in ax.patches:
ax.annotate(f'\n{p.get_height()}', (p.get_x()+0.2, p.get_height()), ha='center', va='top', color='white', size=18)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | NoƩ Melo Locumber |
Solution 4 | Dharman |