前言
热图作为一种数据的可视化表达方法而受到关注,本文将介绍热图的2D和3D绘制方法,供行相关人员参考。
一、热图概述
热图是数据的一种可视化表达的方式,其基本原则是使用颜色辅助表示数字,让数据呈现更直观,对比更明显。其通过将数据矩阵中的各个值按照一定的规律映射成颜色展示,利用颜色的变化来可视化比较数据。
热图应用于数值矩阵时,热图中每个单元格的颜色展示的是行变量和列变量交叉处的数据值的大小,它可以表示相关性,成功率等。理论上,任何一个表格数据都可以转换为热图表示。
根据图形的维度,可以将热图分为二维热图和三维堆叠热图,它们能够分别用于表示不同的独立自变量的影响。
二、二维热图的绘制
我们可以从简单的二维热图开始,表示对应。首先需要一个二维列表或数组来定义要用颜色编码的数据(因变量)。然后,我们还需要两个类别列表或数组(自变量);当然,这些列表中元素的数量需要与各个轴上的数据相匹配。
热图本身是一个imshow
图,其标签设置为自变量的类别。请注意,设置刻度位置(set_xticks
)和刻度标签(set_xticklabels
)非常重要,刻度位置只是升序的整数,而刻度标签是要显示的标签。最后,我们可以通过在每个单元格内创建Text
来显示该因变量单元格的值。
具体代码案例如下所示:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
Distance = ["9", "7", "5"] # 自变量y
GSM = ["17", "35", "60", "80", "100", "120"] # 自变量x
# 因变量,这里用来表示成功率的分布
Success_rate = np.array([[1.0, 1.0, 1.0, 1.0, 0.8, 0.0],
[1.0, 1.0, 0.5, 0.2, 0.1, 0.0],
[1.0, 1.0, 0.2, 0.1, 0.2, 0.0]])
fig, ax = plt.subplots()
im = ax.imshow(Success_rate)
# 设置刻度位置
ax.set_xticks(np.arange(len(GSM)))
ax.set_yticks(np.arange(len(Distance)))
# 设置刻度标签
ax.set_xticklabels(GSM, fontsize="16")
ax.set_yticklabels(Distance, fontsize="16")
# 标注每一个因变量的数值到对应位置
for i in range(len(Distance)):
for j in range(len(GSM)):
text = ax.text(j, i, Success_rate[i, j],
ha="center", va="center", color="b", fontsize="14")
ax.set_title("Matrix of success rate", fontsize="16")
fig.tight_layout()
plt.show()
根据上述代码绘制出的二维热图如下所示。需要说明的是,图中并没有添加横纵坐标轴的名称,用户可以根据实际需求更改或者添加图片内容。
三、三维堆叠热图的绘制
当自变量较多时,如想同时表示三个自变量对因变量的影响,就要考虑使用堆叠热图来表示了。
依此类推,当具有四个独立变量时,那就可以用堆叠热图的排列表示。
单个堆叠热图的案例代码如下所示:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
# 导入因变量数值
white_150 = np.array([[0.8, 0.0, 0.0, 0.0],
[0.8, 0.0, 0.0, 0.0],
[0.9, 0.7, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 0.0]])
white_200 = np.array([[0.7, 0.0, 0.0, 0.0],
[0.7, 0.0, 0.0, 0.0],
[1.0, 0.8, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 0.0]])
white_230 = np.array([[0.0, 0.0, 0.0, 0.0],
[0.5, 0.0, 0.0, 0.0],
[0.2, 0.6, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 0.0]])
white_250 = np.array([[0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0],
[0.0, 0.1, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 0.0]])
# 定义画布
fig = plt.figure(111, figsize=(6,2), facecolor='white')
ax1 = fig.add_subplot(1,2,1, projection='3d') # 主图
ax11 = fig.add_subplot(1, 2, 2) # 色条
# 堆叠图的方位设置
ax1.azim = -20 # azim为方位角
ax1.dist = 9
ax1.elev = 25 # elev为仰角
# 网格绘制
x = np.arange(5)
y = np.arange(6)
X, Y = np.meshgrid(x, y)
# 色系选择
paper_white_150 = cm.ScalarMappable(cmap = "viridis").to_rgba(white_150)
paper_white_200 = cm.ScalarMappable(cmap = "viridis").to_rgba(white_200)
paper_white_230 = cm.ScalarMappable(cmap = "viridis").to_rgba(white_230)
paper_white_250 = cm.ScalarMappable(cmap = "viridis").to_rgba(white_250)
# 分别绘制四个二维热图
surf1 = ax1.plot_surface(X, np.ones(shape=X.shape)+3, Y, rstride=1, cstride=1, facecolors=paper_white_250, linewidth=0, antialiased=True, alpha=1.0)
surf1 = ax1.plot_surface(X, np.ones(shape=X.shape)+2, Y, rstride=1, cstride=1, facecolors=paper_white_230, linewidth=0, antialiased=True, alpha=1.0)
surf1 = ax1.plot_surface(X, np.ones(shape=X.shape)+1, Y, rstride=1, cstride=1, facecolors=paper_white_200, linewidth=0, antialiased=True, alpha=1.0)
surf1 = ax1.plot_surface(X, np.ones(shape=X.shape)+0, Y, rstride=1, cstride=1, facecolors=paper_white_150, linewidth=0, antialiased=True, alpha=1.0)
# 绘制主坐标系并制定各坐标轴的刻度
ax1.tick_params(axis='x', colors='w')
ax1.tick_params(axis='y', colors='w')
ax1.tick_params(axis='z', colors='w')
ax1.w_xaxis.line.set_color((0.5, 0.5, 0.5, 0.05))
ax1.w_yaxis.line.set_color((0.5, 0.5, 0.5, 0.05))
ax1.w_zaxis.line.set_color((0.5, 0.5, 0.5, 0.05))
ax1.set_xticks(range(0,6,1))
ax1.set_yticks(range(1,4,1))
ax1.set_zticks(range(0,5,1))
# 设置三维堆叠热图的xyz的刻度数值
ax1.text(1.5, 1.5, -2.95, "150", zdir=(0,1,0),fontsize = 10,)
ax1.text(2.5, 2.5, -2.5, "200", zdir=(0,1,0),fontsize = 10,)
ax1.text(3.5, 3.5, -2, "230", zdir=(0,1,0),fontsize = 10,)
ax1.text(4.5, 4.5, -1.5, "250", zdir=(0,1,0),fontsize = 10,)
ax1.text(0.5, 0.15, 0.7, "0", zdir=(0,1,0),fontsize = 10,)
ax1.text(0.5, 0.15, 1.7, "50", zdir=(0,1,0),fontsize = 10,)
ax1.text(0.5, 0.15, 2.7, "100", zdir=(0,1,0),fontsize = 10,)
ax1.text(0.5, 0.15, 3.7, "125", zdir=(0,1,0),fontsize = 10,)
ax1.text(0.5, 0.15, 4.7, "150", zdir=(0,1,0),fontsize = 10,)
ax1.text(0.55, 0.25, -0.5, "5", zdir=(0.5,1,0),fontsize = 9,)
ax1.text(0.65, 0.40, -1.0, "30", zdir=(0.5,1,0),fontsize = 9,)
ax1.text(0.75, 0.55, -1.5, "60", zdir=(0.5,1,0),fontsize = 9,)
ax1.text(0.85, 0.70, -2.0, "90", zdir=(0.5,1,0),fontsize = 9,)
# 设置色柱color bar
ax11.set_visible(False)
axin11 = inset_axes(ax11, width="2%", height="75%", loc='center left', borderpad=0)
axin11.tick_params(axis='y', labelsize=12)
norm_cot = mpl.colors.Normalize(vmin=0.0, vmax=1.0)
fig.colorbar(cm.ScalarMappable(norm=norm_cot,cmap="viridis"), shrink=1.0, aspect=5, ax=ax11, cax=axin11)
# 绘制图形
plt.show()
绘制出的三维堆叠热图如下图所示,其主要用于可视化表示三个独立自变量对因变量的影响。实际上,新版的origin软件也集成了堆叠热图的绘制功能,具体可以参考Stacked Heatmap Plot in Origin 2023。
总结
以上就是今天要讲的内容,本文介绍了热图的定义与用途,并展示了Python绘制2D和3D堆叠热图的过程,供相关人员参考。
Reference
[1] CSDN: 科研-什么是热图?
[2] matplotlib官网:Creating annotated heatmaps
[3] stackoverflow: How to plot horizontal stack of heatmaps or a stack of grid?
[4] origin: Stacked Heatmap Plot in Origin 2023
[5] Haomachai W, Dai Z, Manoonpong P. Transition Gradient from Standing to Traveling Waves for Energy-Efficient Slope Climbing of a Gecko-Inspired Robot[J]. IEEE Robotics and Automation Letters, 2024.