You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动