Area plot of TB numbers over the years
1. Python code
Show code
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
# Load data
who_tb_data = pd.read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2025/2025-11-11/who_tb_data.csv' )
# Select and summarize
df = who_tb_data[["country" , "year" , "g_whoregion" , "c_cdr" , "e_mort_num" , "e_inc_num" , "e_mort_exc_tbhiv_num" , "e_mort_tbhiv_num" ]]
mort_summary = (
df.groupby(["g_whoregion" , "year" ], as_index= False )
.agg({"e_mort_exc_tbhiv_num" : "sum" , "e_mort_tbhiv_num" : "sum" })
.rename(columns= {
"e_mort_exc_tbhiv_num" : "mort_nonhiv" ,
"e_mort_tbhiv_num" : "mort_hiv"
})
)
# Reshape long
mort_summary = mort_summary.melt(
id_vars= ["g_whoregion" , "year" ],
value_vars= ["mort_nonhiv" , "mort_hiv" ],
var_name= "mort_type" ,
value_name= "deaths"
)
# Rename and order mortality types
mort_summary['mort_type' ] = mort_summary['mort_type' ].map ({
'mort_hiv' : 'HIV related Tuberculosis Death' ,
'mort_nonhiv' : 'Non-HIV related Tuberculosis Death'
})
mort_summary['mort_type' ] = pd.Categorical(
mort_summary['mort_type' ],
categories= [
'Non-HIV related Tuberculosis Death' ,
'HIV related Tuberculosis Death'
],
ordered= True
)
# Determine plot structure
mort_types = mort_summary['mort_type' ].unique()
fig, axes = plt.subplots(1 , len (mort_types), figsize= (14 , 6 ), sharey= True )
if len (mort_types) == 1 :
axes = [axes]
for ax, mtype in zip (axes, mort_types):
subset = mort_summary[mort_summary['mort_type' ] == mtype]
pivot_df = subset.pivot_table(
index= 'year' , columns= 'g_whoregion' , values= 'deaths' , aggfunc= 'sum'
).fillna(0 )
ax.stackplot(
pivot_df.index,
pivot_df.T.values,
labels= pivot_df.columns
)
ax.set_title(mtype)
ax.set_xlabel("Year" )
ax.set_ylabel("Deaths" )
ax.grid(False )
ax.spines['top' ].set_visible(False )
ax.spines['right' ].set_visible(False )
ax.spines['left' ].set_color("darkgrey" )
ax.spines['bottom' ].set_color("darkgrey" )
ax.yaxis.set_major_formatter(mticker.StrMethodFormatter(' {x:,.0f} ' ))
fig.legend(
pivot_df.columns,
bbox_to_anchor= (0.5 , - 0.08 ),
title= "WHO-Defined Region" ,
loc= "lower center" ,
ncol= 3 ,
frameon= False
)
fig.suptitle("Non-HIV and HIV-related Tuberculosis deaths per WHO-Region" , fontsize= 14 )
plt.tight_layout(rect= [0 , 0 , 1 , 0.95 ])
Back to top