本篇文章由 VeriMake 旧版论坛中备份出的原帖的 Markdown 源码生成
原帖标题为:Python Implementation on "Storytelling with Data"——Figure 2.5: Heatmap
原帖网址为:https://verimake.com/topics/165 (旧版论坛网址,已失效)
原帖作者为:Felix(旧版论坛 id = 28,注册于 2020-04-18 19:59:47)
原帖由作者初次发表于 2020-09-26 18:01:48,最后编辑于 2020-09-26 18:01:48(编辑时间可能不准确)
截至 2021-12-18 14:27:30 备份数据库时,原帖已获得 710 次浏览、0 个点赞、0 条回复
Introduction
"A heatmap is a way to visualize data in tabular format, where in place of the numbers, you leverage colored cells that convey the relative magnitude of the numbers".
Compared to tables, a heatmap helps "our eyes and brains more quickly target the potential points of interest". [1]
Code
Import modules
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
Set style
plt.style.use('seaborn-whitegrid')
Import data
Raw data
# import raw data
data_raw = pd.read_csv('D:/programming/dataset/storytellingwithdata/project/data2.5.csv')
Raw data preview

Processed data
# process data
data_pro = pd.DataFrame(data_raw).to_numpy()
# create column list for column label
col = list(data_raw.columns)[1:]
Processed data and column list preview


Plot
# create two subplots
fig, ax = plt.subplots(1, 2, figsize=(12, 3), dpi=150)
# draw table 1
table_1 = ax[0].table(data_pro, colLabels=[''] + col, cellLoc='center', loc=9)
table_1.set_fontsize(15)
# get all cells as an dictionary object, cell_dict[x, y] refers to row x col y cell
# for every cell, set height and linewidth
cell_dict_1 = table_1.get_celld()
for _row_ in range(0, 7):
for _col_ in range(0, 4):
cell_dict_1[(_row_, _col_)].set_height(.13)
cell_dict_1[(_row_, _col_)].set_linewidth(0)
# draw table 2
table_2 = ax[1].table(data_pro, colLabels = ['']+col, cellLoc='center', loc=9)
table_2.set_fontsize(15)
# get all cells as an dictionary object, cell_dict[x, y] refers to row x col y cell
# for every cell, set height and linewidth
cell_dict_2 = table_2.get_celld()
for _row_ in range(0, 7):
for _col_ in range(0, 4):
cell_dict_2[(_row_, _col_)].set_height(.13)
cell_dict_2[(_row_, _col_)].set_linewidth(0)
# for cell containing data,
# set background color as royalblue, set transparency and text color accordingly
if _row_ != 0 and _col_ != 0:
# get number value
number = float(data_pro[_row_ - 1, _col_][:-1])
cell_dict_2[_row_, _col_].set_color('royalblue')
# set alpha based on number value
alpha = number/100
cell_dict_2[_row_, _col_].set_alpha(alpha)
# for light background color, set text color lightsteelblue
# for dark background color, set text color white
if number < 27:
cell_dict_2[_row_, _col_].get_text().set_color('lightsteelblue')
else:
cell_dict_2[_row_, _col_].get_text().set_color('white')
# remove axises for both plots
ax[0].axis('off')
ax[1].axis('off')
# set boundries for both plots
x = np.arange(0, 5, 0.01)
y = np.ones(len(x))
y = y * 100
ax[0].plot(x, y, c='white')
ax[1].plot(x, y, c='white')
x = np.arange(0, 5, 0.01)
y = np.ones(len(x))
y = y * 0
ax[0].plot(x, y, c='white')
ax[1].plot(x, y, c='white')
# draw line y = 86 and line x = 1.13 in grey for both plots
x = np.arange(0, 5, 0.01)
y = np.ones(len(x))
y = y * 86
ax[0].plot(x, y, c='lightgrey')
ax[1].plot(x, y, c='lightgrey')
y = np.arange(3, 97, 0.01)
x = np.ones(len(y))
x = x * 1.13
ax[0].plot(x, y, c='lightgrey')
ax[1].plot(x, y, c='lightgrey')
Result

Reference
[1] Cole Nussbaumer Knaflic, Storytelling with Data