It's important to iterate through each of the columns and plot them as you go in a for-loop. Then reassign the column names. Here is a full example. You should be able to copy and paste this code, then run it.
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
# your data
df = pd.DataFrame(
{
'Early': {'A': 824, 'B': 701, 'C': 1050, 'D': 764, 'E': 993},
'Long Overdue': {'A': 238, 'B': 270, 'C': 489, 'D': 549, 'E': 471},
'On Time': {'A': 1021, 'B': 1025, 'C': 120, 'D': 71, 'E': 57},
'Overdue': {'A': 493, 'B': 580, 'C': 917, 'D': 1192, 'E': 1055}
})
# set the figure size
fig, ax = plt.subplots(figsize = (10,7), dpi = 200)
# select the colors you would like to use for each category
colors = ['skyblue','goldenrod','slateblue','seagreen']
# used to set the title, y, and x labels
ax.set_title('\nTrain Times\n', fontsize = 14)
ax.set_xlabel('\nCategories\n', fontsize = 14)
ax.set_ylabel('\nValues\n', fontsize = 14)
# create an offsetting x axis to iterate over within each group
x_axis = np.arange(len(df))+1
# center each group of columns
offset = -0.3
# iterate through each set of values and the colors associated with each
# category
for index, col_name, color in zip(x_axis, df.columns, colors):
x = x_axis+offset
height = df[col_name].values
ax.bar(
x,
height,
width = 0.2,
color = color,
alpha = 0.8,
label = col_name
)
offset += 0.2
# set the annotations
props = dict(boxstyle='round', facecolor='white', alpha=1)
for horizontal, vertical in zip(x, height):
ax.text(
horizontal-len(str(vertical))/30,
vertical+26,
str(vertical),
fontsize=12,
bbox=props)
# set the y limits so the legend appears above the bars
ax.set_ylim(0, df.to_numpy().max()*1.25)
# relabel the x axis
ax.set_xticks(x_axis) # offset values
ax.set_xticklabels(df.index.to_list()) # set the labels for each group
# the legend can be set to multiple values. 'Best' has Matplotlib automatically set the location.
# setting ncol to the length of the dataframe columns sets the legend horizontally by the length
# of the columns
plt.legend(loc = 'best', ncol=len(df.columns), fontsize = 12)
plt.show()
This should give you the following plot. I tried to match the colors as closely as possible to the picture you provided. However, you can choose your own. Here is a link to a chart and list of all the colors available for you to use. Chart of available Matplotlib colors
