Stacked bar chart with Python

Cedric Vidonne

Lei Chen

Stacked bar chart with Python

Stacked bar charts stack horizontal bars that represent different groups one after another. The length of the stacked bar shows the combined value of the groups. They show the cumulative values of data items and compare parts to the whole.

More about: Stacked bar chart


Basic stacked bar chart

# import libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from textwrap import wrap
plt.style.use(['unhcrpyplotstyle','bar'])

#load data set
df = pd.read_csv('https://raw.githubusercontent.com/GDS-ODSSS/unhcr-dataviz-platform/master/data/comparison/bar_stacked.csv')

#reshape df from long to wide
df = df.pivot(index='country_origin', columns='population_type', values='population_number')
df = df.reset_index()

#sort by total descending order
df['Total'] = df.sum(numeric_only=True, axis=1)
df = df.sort_values("Total", ascending=True)
df= df.fillna(0)

#prepare data array for plotting
x = df['country_origin']

y1 = df['REF']
y2 = df['VDA']
y3 = df['ASY']
b_y3 = np.add(y1, y2)

#wrap long labels
x = [ '\n'.join(wrap(l, 20)) for l in x ]

#plot the chart
fig, ax = plt.subplots()
rect1=ax.barh(x, y1, label='Refugees')
rect2=ax.barh(x, y2, left=y1, label='Venezuelans dispalced abrod')
rect3=ax.barh(x, y3, left=b_y3, label='Asylum-seekers')

#set chart title
ax.set_title('People displaced across borders by country of origin | 2021')

#set chart legend
ax.legend(loc=(0,1.02), ncol=3)

#set y-axis title
ax.set_xlabel('Number of people (millions)')

#set y-axis label 
ax.tick_params(labelbottom=True)

#show grid below the bars
ax.grid(axis='x')

#format x-axis tick labels
def number_formatter(x, pos):
    if x >= 1e6:
        s = '{:1.0f}M'.format(x*1e-6)
    elif x < 1e6 and x >= 1e3:
        s = '{:1.0f}K'.format(x*1e-3)
    else: 
        s = '{:1.0f}'.format(x)
    return s
ax.xaxis.set_major_formatter(number_formatter)

#set chart source and copyright
plt.annotate('Source: UNHCR Refugee Data Finder', (0,0), (0, -40), xycoords='axes fraction', textcoords='offset points', va='top', color = '#666666', fontsize=9)
plt.annotate('©UNHCR, The UN Refugee Agency', (0,0), (0, -50), xycoords='axes fraction', textcoords='offset points', va='top', color = '#666666', fontsize=9)

#adjust chart margin and layout
fig.tight_layout()

#show chart
plt.show()

A stacked bar chart showing people displaced across borders by country of origin | 2021


Stacked bar chart with data label

# import libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from textwrap import wrap
plt.style.use(['unhcrpyplotstyle','bar'])

#load data set
df = pd.read_csv('https://raw.githubusercontent.com/GDS-ODSSS/unhcr-dataviz-platform/master/data/comparison/bar_stacked.csv')

#reshape df from long to wide
df = df.pivot(index='country_origin', columns='population_type', values='population_number')
df = df.reset_index()

#sort by total descending order
df['Total'] = df.sum(numeric_only=True, axis=1)
df = df.sort_values("Total", ascending=True)
df= df.fillna(0)

#compute data array for plotting

x = df['country_origin']
y1 = df['REF']
y2 = df['VDA']
y3 = df['ASY']
b_y3 = np.add(y1, y2)

#wrap long labels
x = [ '\n'.join(wrap(l, 20)) for l in x ]

#plot the chart
fig, ax = plt.subplots()
rect2=ax.barh(x, y1,label='Refugees')
rect1=ax.barh(x, y2, left=y1, label='Venezuelans dispalced abrod')
rect3=ax.barh(x, y3, left=b_y3, label='Asylum-seekers')

#set chart title
ax.set_title('People displaced across borders by country of origin | 2021', pad=50)

#set subtitle
plt.suptitle('Number of people in millions', x=0.362, y=0.88)

#set chart legend
ax.legend(loc=(0,1.02), ncol=3)

# set formatted data label
ax.bar_label(rect1, labels=[f'{x*1e-6:,.1f}' for x in rect1.datavalues], label_type='center', padding=3,color='#ffffff')
ax.bar_label(rect2, labels=[f'{x*1e-6:,.1f}' for x in rect2.datavalues], label_type='center', padding=3,color='#ffffff')
ax.bar_label(rect3, labels=[f'{x*1e-6:,.1f}' for x in rect3.datavalues], label_type='center', padding=3,color='#ffffff')

#set chart source and copyright
plt.annotate('Source: UNHCR Refugee Data Finder', (0,0), (0, -10), xycoords='axes fraction', textcoords='offset points', va='top', color = '#666666', fontsize=9)
plt.annotate('©UNHCR, The UN Refugee Agency', (0,0), (0, -20), xycoords='axes fraction', textcoords='offset points', va='top', color = '#666666', fontsize=9)

#adjust chart margin and layout
fig.tight_layout()

#show chart
plt.show()

A stacked bar chart showing people displaced across borders by country of origin | 2021


Related chart with Python