Last active
April 11, 2020 21:42
-
-
Save barrysmyth/c51a8aec88d77c02f5f1e7de3fcbbf66 to your computer and use it in GitHub Desktop.
A short snippet of code to reproduce the BBC's COVID-19 lockdown chart.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fig, ax = plt.subplots(figsize=(30, len(use_countries)*1.25)) | |
# ---------------------------- | |
# The Stringency Index Heatmap | |
# ---------------------------- | |
# For maximum flexibility we use a separate axis to plot the heatmap's | |
# colour bar (horizontally) as the SI legend. | |
cbar_ax = fig.add_axes([.15, .17, .38, 3/len(stringency_for_country_by_date)]) | |
# The heatmap itself is straightfoward with one caveat: after much fiddling I had to | |
# set its xticklabels parameter to the date interval we are using. | |
sns.heatmap(stringency_for_country_by_date.loc[use_countries], ax=ax, | |
linewidths=1, cmap=stringency_cmap, cbar=True, xticklabels=date_interval, zorder=10, | |
cbar_ax=cbar_ax, cbar_kws=dict(orientation='horizontal', ticks=[]) | |
) | |
# ---------------------------- | |
# The First Cases Heatmap | |
# ---------------------------- | |
# The first cases plot doesn't look like a heatmap. It looks like a variation of a | |
# line graph, but this doesn't work. Notice that the first case markers for each country | |
# are not regular matplotlib markers, they are vertical lines that align and match with the | |
# the SI cells. | |
bx = ax.twinx() # We need a duplicate axis | |
# The first cases heatmap | |
sns.heatmap(first_cases_for_country_by_date.loc[use_countries], ax=ax, | |
linewidths=.15, cmap=['k'], cbar=False, xticklabels=14, zorder=10) | |
# ---------------------------- | |
# Axes, labels & grid-lines | |
# ---------------------------- | |
ax.set_xticklabels(date_labels) | |
# We want a duplicate x axis on the top too. | |
ax2 = ax.twiny() | |
ax2.set_xticks(ax.get_xticks()) | |
ax2.set_xticklabels(ax.get_xticklabels()) | |
# Remove axes ticks | |
ax.tick_params(axis='both', length = 0) | |
ax2.tick_params(axis='both', length = 0) | |
# Draw the vertical gridlines | |
ax.grid(axis='x', lw=2) | |
# We dont need labels for the x axes. | |
ax.set_xlabel('') | |
ax.set_ylabel('') | |
# Shift the y axis labels to the right-hand side. | |
ax.set_yticklabels(ax.get_yticklabels(), rotation=0, fontweight='bold') | |
ax.yaxis.tick_right() | |
# We don't need the y-axis ticks/labels for teh second y-axis. | |
bx.set_yticks([]) | |
bx.set_yticklabels([]) | |
ax.set_xlim(14) | |
bx.set_xlim(14) | |
# Remove the frame around the plot | |
sns.despine(left=True, bottom=True, right=True) | |
# A title and key for the SI legend. | |
bx.annotate('Stringency Index', xy=(.04, .1), xycoords='axes fraction', fontweight='bold') | |
cbar_ax.annotate(' Low Medium High Very High', xy=(.04, .3), xycoords='axes fraction', fontsize=40, fontweight='bold', color='white') | |
# A title for the graph. | |
ax.set_title('Countries in Lockdown (2020)\n', fontweight='bold', loc='left') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment