Python热力图技术需求:修改颜色映射并实现不对称效果
实现热力图的不对称颜色映射方案
针对你的需求——修改现有热力图代码,实现不对称颜色映射效果,我整理了一套完整的实现方案,结合你的重叠数据和基础代码来讲解:
第一步:先整理热力图所需的矩阵数据
你的原始数据是两两curation的重叠值,需要先转换成7×7的方阵(对应curation1到7),如果不需要对称显示(比如只保留原始的上三角数据),可以不用填充对称位置:
# 把你的原始数据转换成DataFrame data = [ [1,2,0], [1,3,1098], [1,4,11], [1,5,137], [1,6,105], [1,7,338], [2,3,351], [2,4,0], [2,5,1], [2,6,0], [2,7,0], [3,4,132], [3,5,215], [3,6,91], [3,7,191], [4,5,6], [4,6,10], [4,7,19], [5,6,37], [5,7,95], [6,7,146] ] df = pd.DataFrame(data, columns=['curation1', 'curation2', 'overlap']) # 创建7×7的空矩阵,填充初始值0 size = 7 heatmap_data = pd.DataFrame(index=range(1, size+1), columns=range(1, size+1), dtype=int) heatmap_data.fillna(0, inplace=True) # 填充原始数据到矩阵中 for _, row in df.iterrows(): i, j, val = row['curation1'], row['curation2'], row['overlap'] heatmap_data.loc[i, j] = val # 如果你不需要对称矩阵,就注释掉下面这句 # heatmap_data.loc[j, i] = val
第二步:实现不对称颜色映射的核心设置
不对称颜色映射的关键是让颜色的渐变不围绕单一中间值对称,我们有两种常用实现方式:
方式1:用TwoSlopeNorm实现不对称归一化
TwoSlopeNorm可以让你指定一个分界点(比如数据的中位数、某个业务阈值),然后对分界点上下的数值应用不同的缩放比例,这样颜色的渐变程度就不对称了。比如你的数据最大值1098远大于中位数91,用这个方法可以避免高数值区间的颜色被过度压缩:
from matplotlib.colors import TwoSlopeNorm # 获取数据的极值和分界点(这里用中位数,你可以换成自定义值比如200) vmin = df['overlap'].min() vmax = df['overlap'].max() split_val = df['overlap'].median() # 你的数据中位数是91 # 创建不对称归一化对象 norm = TwoSlopeNorm(vmin=vmin, vcenter=split_val, vmax=vmax) # 搭配一个双色colormap,比如coolwarm,也可以用自定义颜色 cmap = cm.get_cmap('coolwarm')
方式2:自定义完全不对称的颜色分段
如果你想更灵活地控制不同数值区间的颜色(比如低数值用蓝色系渐变,高数值用红色系渐变,且两段的颜色过渡完全不同),可以自定义colormap,再搭配TwoSlopeNorm使用:
from matplotlib.colors import LinearSegmentedColormap # 定义颜色分段:0-91用蓝色到浅蓝,91-1098用黄色到红色 colors = [ (0.0, '#0000ff'), # 最小值对应深蓝色 (0.5, '#87cefa'), # 分界点对应浅蓝 (0.5, '#ffff00'), # 分界点对应黄色 (1.0, '#ff0000') # 最大值对应红色 ] # 创建自定义colormap custom_cmap = LinearSegmentedColormap.from_list('asym_cmap', colors) # 同样用TwoSlopeNorm来绑定数值范围和颜色映射 norm = TwoSlopeNorm(vmin=vmin, vcenter=split_val, vmax=vmax)
第三步:修改你的现有代码,应用不对称映射
把上面的设置整合到你的代码中,完整的绘制代码如下:
import sys import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.ticker as ticker import matplotlib.cm as cm import matplotlib as mpl import matplotlib.pyplot as plt from matplotlib.backends.backend_pdf import PdfPages from matplotlib.colors import TwoSlopeNorm, LinearSegmentedColormap # ---------------------- 数据准备 ---------------------- data = [ [1,2,0], [1,3,1098], [1,4,11], [1,5,137], [1,6,105], [1,7,338], [2,3,351], [2,4,0], [2,5,1], [2,6,0], [2,7,0], [3,4,132], [3,5,215], [3,6,91], [3,7,191], [4,5,6], [4,6,10], [4,7,19], [5,6,37], [5,7,95], [6,7,146] ] df = pd.DataFrame(data, columns=['curation1', 'curation2', 'overlap']) size = 7 heatmap_data = pd.DataFrame(index=range(1, size+1), columns=range(1, size+1), dtype=int) heatmap_data.fillna(0, inplace=True) for _, row in df.iterrows(): i, j, val = row['curation1'], row['curation2'], row['overlap'] heatmap_data.loc[i, j] = val # 不需要对称矩阵就注释下面这句 # heatmap_data.loc[j, i] = val # ---------------------- 不对称颜色映射设置 ---------------------- vmin = df['overlap'].min() vmax = df['overlap'].max() split_val = df['overlap'].median() # 自定义分界点可替换这里的值 # 选择方式1或方式2的映射设置 # 方式1:用现有colormap + TwoSlopeNorm norm = TwoSlopeNorm(vmin=vmin, vcenter=split_val, vmax=vmax) cmap = cm.get_cmap('coolwarm') # 方式2:自定义colormap(用这个就注释方式1的cmap行) # colors = [ # (0.0, '#0000ff'), # (0.5, '#87cefa'), # (0.5, '#ffff00'), # (1.0, '#ff0000') # ] # cmap = LinearSegmentedColormap.from_list('asym_cmap', colors) # ---------------------- 绘制热力图 ---------------------- fig, ax = plt.subplots(figsize=(8, 6)) # 绘制热力图,应用自定义的norm和cmap im = ax.imshow(heatmap_data.values, cmap=cmap, norm=norm, origin='upper') # 设置坐标轴标签 ax.set_xticks(range(size)) ax.set_xticklabels(range(1, size+1)) ax.set_yticks(range(size)) ax.set_yticklabels(range(1, size+1)) # 添加颜色条,标注含义 cbar = fig.colorbar(im, ax=ax) cbar.set_label('Overlap Count') # 在每个单元格标注具体数值 for i in range(size): for j in range(size): text = ax.text(j, i, heatmap_data.iloc[i, j], ha='center', va='center', color='black') plt.title('Asymmetric Colormap Heatmap of Curation Overlaps') # 保存到PDF文件 with PdfPages('asymmetric_heatmap.pdf') as pdf: pdf.savefig(fig) plt.close()
关键说明
TwoSlopeNorm是实现不对称视觉效果的核心,它让分界点上下的数值被归一化到不同的范围,解决了数据分布不均(比如你的数据有一个极大值1098)导致的颜色区分不明显问题。- 如果你的热力图只需要展示原始的非对称数据(比如上三角),记得注释掉填充对称位置的代码,这样颜色映射的不对称效果会更突出。
- 你可以根据业务需求调整分界点(比如换成200),或者修改自定义colormap的颜色,来适配不同的可视化需求。
内容的提问来源于stack exchange,提问作者Slowat_Kela




