I'm trying to make a graph that would look roughly like this.
Here's some sample data:
data = {
"date": ["2020-07-01", "2020-07-01", "2020-07-01", "2020-08-01", "2020-08-01", "2020-08-01", "2020-09-01",
"2020-09-01", "2020-09-01", "2020-10-01", "2020-10-01", "2020-10-01", "2020-11-01", "2020-11-01",
"2020-11-01", "2020-12-01", "2020-12-01", "2020-12-01", "2021-01-01", "2021-01-01", "2021-01-01",
"2021-02-01", "2021-02-01", "2021-02-01", "2021-03-01", "2021-03-01", "2021-03-01", "2021-04-01",
"2021-04-01", "2021-04-01", "2021-05-01", "2021-05-01", "2021-05-01", "2021-06-01", "2021-06-01",
"2021-06-01"],
"col2": ["A", "B", "C", "A", "B", "C", "A", "B", "C", "A", "B", "C", "A", "B", "C", "A", "B", "C", "A", "B", "C",
"A", "B", "C", "A", "B", "C", "A", "B", "C", "A", "B", "C", "A", "B", "C"],
"col3": [24, 45, 0.0, 18, 47, 0.0, 31, 50, 0.0, 21, 40, 565, 34, 64, 220, 724, 3598, 1493,
286, 127, 185, 37, 94, 233, 22, 18, 170, 111, 45, 186, 17, 106, 114, 12, 50, 122]
}
I use this code to make the multiindex dataframe, I also need a single datetime index for the x axis formatting.
df = pd.DataFrame(data)
df["date"] = pd.to_datetime(df["date"])
df = df.groupby(["date", "col2"]).sum()
df_single_index = df.groupby("date").sum()
This is the code I have to make most of the graph:
fig, ax = plt.subplots(figsize=(11.96, 4.42))
df.unstack().plot(kind='bar', ax=ax, stacked=True, zorder=3)
ax.set_xticks(range(df_single_index.index.size))
ax.set_xticklabels([date.strftime('%b\n%Y') if date.year != df_single_index.index[idx - 1].year
else date.strftime('%b') for idx, date in enumerate(df_single_index.index)])
ax.figure.autofmt_xdate(rotation=0, ha='center')
ax.tick_params(axis='x', which="major", bottom=False)
x_locator = FixedLocator(np.arange(-0.5, (len(df_single_index) + 0.5), 1))
ax.tick_params(axis='x', which="minor", direction="out", length=15, width=1)
ax.xaxis.set_minor_locator(x_locator)
plt.grid(which="major", axis="y", zorder=0)
Most works fine, except the legend doesn't look good.
Adding this code fixed the legend and changed the colours of the legend:
colors = {"A": (1, 0.75, 0), "B": (0.498, 0.498, 0.498), "C": (0, 0.7, 0.76)}
labels = list(colors.keys())
handles = [plt.Rectangle((0, 0), 1, 1, color=colors[label]) for label in labels]
plt.legend(handles, labels)
But now the bars don't match the legend and adding the colour dictionary as a parameter in the graph only throws a KeyError. I can't figure out how else to go about it. Any advice will be appreciated.



