5

I'm trying to annotate the values for a stacked horizontal bar graph created using pandas. Current code is below

import pandas as pd 
import matplotlib.pyplot as plt
import numpy as np

d = {'group 1': [1, 2, 5, 7, 4, 5, 10],
     'group 2': [5, 6, 1, 8, 2, 6, 2],
     'group 3': [12, 2, 2, 4, 4, 8, 4]}
df = pd.DataFrame(d)

ax = df.plot.barh(stacked=True, figsize=(10,12))

for p in ax.patches:
    ax.annotate(str(p.get_x()), xy=(p.get_x(), p.get_y()+0.2))

plt.legend(bbox_to_anchor=(0, -0.15), loc=3, prop={'size': 14}, frameon=False)

The problem is the annotation method I used gives the x starting points and not the values of each segment. I'd like to be able to annotate values of each segment in the center of each segment for each of the bars.

example

edit: for clarity, what I would like to achieve is something like this where the values are centered horizontally (and vertically) for each segment:

enter image description here

0

3 Answers 3

7

You can use the patches bbox to get the information you want.

ax = df.plot.barh(stacked=True, figsize=(10, 12))
for p in ax.patches:
    left, bottom, width, height = p.get_bbox().bounds
    ax.annotate(str(width), xy=(left+width/2, bottom+height/2), 
                ha='center', va='center')

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

4

Another possible solution is to get your df.values to a flatten array via values = df.values.flatten("F")

%matplotlib inline
import pandas as pd 
import matplotlib.pyplot as plt
import numpy as np

d = {'group 1': [1, 2, 5, 7, 4, 5, 10],
     'group 2': [5, 6, 1, 8, 2, 6, 2],
     'group 3': [12, 2, 2, 4, 4, 8, 4]}
df = pd.DataFrame(d)

ax = df.plot.barh(stacked=True, figsize=(10,12))

values = df.values.flatten("F")

for i, p in enumerate(ax.patches):
    ax.annotate(str(values[i]), xy=(p.get_x()+ values[i]/2, p.get_y()+0.2))

plt.legend(bbox_to_anchor=(0, -0.15), loc=3, prop={'size': 14}, frameon=False);

enter image description here

Comments

0
  • From matplotlib 3.4.0 use matplotlib.pyplot.bar_label
    • The labels parameter can be used to customize annotations, but it's not required.
    • See this answer for additional details and examples.
  • Each group of containers must be iterated through to add labels.
  • Tested in python 3.10, pandas 1.4.2, matplotlib 3.5.1

Horizontal Stacked

d = {'group 1': [1, 2, 5, 7, 4, 5, 10],
     'group 2': [5, 6, 1, 8, 2, 6, 2],
     'group 3': [12, 2, 2, 4, 4, 8, 4]}
df = pd.DataFrame(d)

# add tot to sort the bars
df['tot'] = df.sum(axis=1)

# sort
df = df.sort_values('tot')

# plot all columns except tot
ax = df.iloc[:, :-1].plot.barh(stacked=True, figsize=(10, 12))

# iterate through each group of bars
for c in ax.containers:

    # format the number of decimal places (if needed) and replace 0 with an empty string
    labels = [f'{w:.0f}' if (w := v.get_width()) > 0 else '' for v in c ]
    
    ax.bar_label(c, labels=labels, label_type='center')

enter image description here

Horizontal Grouped

  • Not stacked is a better presentation of the data, because it is easier to compare bar lengths visually.
# plot all columns except tot
ax = df.iloc[:, :-1].plot.barh(stacked=False, figsize=(8, 9))

# iterate through each group of bars
for c in ax.containers:

    # format the number of decimal places (if needed) and replace 0 with an empty string
    labels = [f'{w:.0f}' if (w := v.get_width()) > 0 else '' for v in c ]
    
    ax.bar_label(c, labels=labels, label_type='center')

enter image description here

df view

   group 1  group 2  group 3  tot
2        5        1        2    8
1        2        6        2   10
4        4        2        4   10
6       10        2        4   16
0        1        5       12   18
3        7        8        4   19
5        5        6        8   19

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.