Gantt chart / Timeline in matplotlib
In this tutorial I will show you how to create Gantt charts using Python and Matplotlib. For more matplotlib charts, check out the gallery:

Important notes:
1. This are my personal notes, so apologies if some explanations and notations are missing.
Gantt charts in matplotlib
This is what we will be creating:

Import the packages
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
Create the data
data = {
"war": ['World War I','World War II','Korea','Vietnam','Guf War','Iraq','Afghanistan'],
"start" : [1914,1939,1950,1965,1990,2003,2001],
"end" : [1918,1945,1953,1973,1991,2011,2020]
}
#convert array to pandas dataframe
df = pd.DataFrame(data)
#convert array to pandas dataframe
df['start'] = df['start'].astype(int)
df['end'] = df['end'].astype(int) #change the type to number
df['year_Diff'] = df['end'] - df['start']
war | start | end | year_Diff | |
---|---|---|---|---|
0 | World War I | 1914 | 1918 | 4 |
1 | World War II | 1939 | 1945 | 6 |
2 | Korea | 1950 | 1953 | 3 |
3 | Vietnam | 1965 | 1973 | 8 |
4 | Guf War | 1990 | 1991 | 1 |
5 | Iraq | 2003 | 2011 | 8 |
6 | Afghanistan | 2001 | 2020 | 19 |
Define variables
#convert the columns into numpy 2D array
x_coord = df[['start','year_Diff']].to_numpy()
#array for the range annotation
arrow = df[['start','end']].to_numpy()
Plot the chart
fig, ax = plt.subplots(figsize=(18, 4), facecolor="white")
#add the timeline
ax.broken_barh([(1905, 117)], (20, 5), color = "#eeeeee")
#add a for afgahnistan for each event
for st, ed, text, arr, xcoord in zip(start[-1:],end[-1:], war[-1:], arrow[-1:], x_coord[-1:]): #remove afghanistan
#the max and min for the line is specified in percentage
ax.broken_barh([xcoord], (20, 5), color=['#dbdbdb'], alpha=0.7,
linewidth=2,
edgecolor=['#E82E22'],
linestyle='dashed', hatch='xx' )
#the max and min for the line is specified in percentage
ax.axvline(x=st, ymin = 0.17, ymax = 0.42, color='#000', linestyle= "-")
ax.axvline(x=ed, ymin = 0.34, ymax = 0.42, color='#000', linestyle= "-")
ax.annotate(text, (st , 15),xytext=(4, -3), textcoords='offset points', ha='left', va='bottom')
ax.annotate(str(st) + " - " + str(ed), (st , 12),xytext=(4, -3), textcoords='offset points', ha='left', va='bottom')
ax.annotate('', xy = (arr[0],17), xycoords='data', xytext=(arr[1],17),
arrowprops=dict(arrowstyle='-', lw=1, shrinkA=0, shrinkB=0, color = "#000",))
#add a line for each event
for st, ed, text, arr, xcoord in zip(start[:-1],end[:-1], war[:-1], arrow[:-1], x_coord[:-1]): #remove afghanistan
#the max and min for the line is specified in percentage
ax.broken_barh([xcoord], (20, 5), color = "#E82E22", hatch='/')
#the max and min for the line is specified in percentage
ax.axvline(x=st, ymin = 0.57, ymax = 0.8, color='#000', linestyle= "-")
ax.axvline(x=ed, ymin = 0.57, ymax = 0.62, color='#000', linestyle= "-")
ax.annotate(text, (st , 32),xytext=(4, -3), textcoords='offset points', ha='left', va='bottom')
ax.annotate(str(st) + " - " + str(ed), (st , 29),xytext=(4, -3), textcoords='offset points', ha='left', va='bottom')
ax.annotate('', xy = (arr[0],27), xycoords='data', xytext=(arr[1],27),
arrowprops=dict(arrowstyle='-', lw=1, shrinkA=0, shrinkB=0, color = "#000",))
ax.set_ylim(5, 40)
ax.set_xlim(1905, 2022)
# Hide grid lines
plt.box(False) #remove box
# Hide axes ticks
plt.axis('off') #turn all axis off
plt.yticks([])

Was this helpful?
Reader Interactions