如何将Matplotlib 3D直方图颜色设置为随高度变化(类热力图)
给3D直方图添加高度关联的热力图配色
我来帮你搞定这个需求!要让3D直方图的颜色随柱子高度变化(类似热力图),核心是把每个柱子的高度值映射到颜色映射表(colormap)上,给每个柱子单独设置颜色。下面是修改后的完整代码,我会把关键步骤标出来:
from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np from matplotlib.cm import ScalarMappable from matplotlib.colors import Normalize fig = plt.figure(figsize=(10, 7)) ax = fig.add_subplot(111, projection='3d') nbins = 1000 mean_list = [366, 657, 594, 1200] scale_list = [15,50,19,7] height_list = [1200, 300, 900, 600] z_positions = [30, 15, 10, 0] # 先收集所有柱子的高度,用于统一归一化颜色范围 all_heights = [] hist_data = [] # 第一步:计算每个数据集的直方图数据 for n in range(len(z_positions)): ys = np.random.normal(loc=mean_list[n], scale=scale_list[n], size=height_list[n]) # 计算直方图:bin高度、bin边缘 counts, bins = np.histogram(ys, bins=nbins) # 保存bin的中心位置(用来定位柱子) bin_centers = (bins[:-1] + bins[1:]) / 2 hist_data.append((bin_centers, counts, z_positions[n])) all_heights.extend(counts) # 第二步:设置颜色归一化和颜色映射 norm = Normalize(vmin=np.min(all_heights), vmax=np.max(all_heights)) cmap = plt.get_cmap('viridis') # 可以换成你喜欢的colormap,比如'plasma'、'coolwarm' # 第三步:逐个绘制柱子并设置颜色 for centers, counts, z in hist_data: x = z # z轴位置作为x坐标(对应原代码的z参数) y = centers # bin中心作为y坐标 dx = 2 # 柱子在x方向的宽度,可调整 dy = bins[1] - bins[0] # bin的宽度,即柱子在y方向的宽度 dz = counts # 柱子高度 # 给每个柱子生成对应颜色 colors = cmap(norm(dz)) # 绘制3D柱子,每个柱子单独设置颜色 ax.bar3d(x, y, 0, dx, dy, dz, color=colors) # 添加颜色条,方便查看高度和颜色的对应关系 sm = ScalarMappable(norm=norm, cmap=cmap) sm.set_array([]) fig.colorbar(sm, ax=ax, pad=0.1, label='柱子高度') # 设置坐标轴标签 ax.set_xlabel('Z层位置') ax.set_ylabel('Y轴数值') ax.set_zlabel('柱子高度') plt.tight_layout() plt.show()
关键细节说明:
- 统一颜色范围:先收集所有柱子的高度再做归一化,这样不同Z层的柱子颜色尺度一致,不会出现某一层颜色偏深、另一层偏浅的情况。
- 颜色映射选择:代码里用的是
viridis(matplotlib默认的友好配色),你可以换成plasma、coolwarm等其他colormap,直接修改plt.get_cmap()的参数就行。 - 柱子尺寸调整:
dx是柱子在X方向的宽度,dy是自动计算的bin宽度,你可以根据需求调整这些值让直方图更美观。 - 颜色条:添加颜色条能让观看者直观对应颜色和高度的关系,提升图表可读性。
内容的提问来源于stack exchange,提问作者Jan
相关产品推荐
相关产品推荐

