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() 
0

1 Answer 1

3

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

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

3 Comments

You're welcome. I wasn't sure about the order of the labels. Did I get the labels in the right place?
the order is reversed,but it's not a huge problem
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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.