1

I want something like on the image

enter image description here

here is my code:

import matplotlib.pyplot as plt
import pandas as pd

plt.style.use('seaborn-notebook')

data = {
    'Unmarried woman': [36, 23, 28, 20, 16],
    'Married woman': [26, 38, 49, 14, 38]
}

unmarried_labels = ['30–55', '14–50', '16-59', '16-24', '13-26']
married_labels = ['25–50', '29–59', '34–89', '11–18', '33–55']

df = pd.DataFrame(data, columns=['Unmarried woman', 'Married woman'],
                  index=['Africa', 'Asia', 'Latin America', 'Northern America',
                         'Europe'])

df.plot.barh()

plt.title(
    'Abortion rate per 1000 women aged 15–44 y. by marital status (2010–2014)',
    fontweight='bold', fontsize=11)

plt.show() 
Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
maksym
  • 11
  • 3

1 Answers1

2

As of Matplotlib 3.4.0 this can be accomplished with bar_labels and zipping containers with the labels:

# Save axes returned from DataFrame plot
ax = df.plot.barh()
# Iterate over containers and all_labels together
for container, labels in zip(ax.containers, all_labels):
    ax.bar_label(container, labels=labels, label_type='center')
  • Labels will align with indexes of the DataFrame:
    • The first list in all_labels will align with column 0 (Unmarried woman) and continue across the columns
    • Index 0 in each sub-list (labels) will align with index 0 in the DataFrame which is Africa and continue down the rows.

All Together:

import matplotlib.pyplot as plt
import pandas as pd

plt.style.use('seaborn-notebook')

unmarried_labels = ['30–55', '14–50', '16-59', '16-24', '13-26']
married_labels = ['25–50', '29–59', '34–89', '11–18', '33–55']
all_labels = [unmarried_labels, married_labels]

df = pd.DataFrame({'Unmarried woman': [36, 23, 28, 20, 16],
                   'Married woman': [26, 38, 49, 14, 38]},
                  columns=['Unmarried woman', 'Married woman'],
                  index=['Africa', 'Asia', 'Latin America', 'Northern America',
                         'Europe'])

# Save axes returned from DataFrame plot
ax = df.plot.barh()
# Iterate over containers and all_labels together
for container, labels in zip(ax.containers, all_labels):
    ax.bar_label(container, labels=labels, label_type='center')

plt.title(
    'Abortion rate per 1000 women aged 15–44 y. by marital status (2010–2014)',
    fontweight='bold',
    fontsize=11
)

plt.tight_layout()
plt.show()

plot

Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
  • You're welcome. I wasn't sure about the order of the labels. Did I get the labels in the right place? – Henry Ecker Jun 26 '21 at 14:11
  • 1
    the order is reversed,but it's not a huge problem – maksym Jun 26 '21 at 14:15
  • I wasn't sure the label had `married_labels[0]` on Europe which to me meant `'25–50'` but I thought you'd have the labels in the correct order. Regardless I've updated my answer to reflect the correct ordering. – Henry Ecker Jun 26 '21 at 14:19