You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中为不同数值范围数据集生成带独立刻度的聚类热力图?

嘿,这个问题太典型了——当两个数据集尺度差得这么多的时候,直接丢进clustermap聚类,结果肯定会被1000-5000那组数据完全主导,0-1的特征根本发挥不了作用。我给你一套可行的方案,既能保证聚类的公平性,又能画出带独立刻度的合并热力图:

第一步:先给数据做标准化,确保聚类公平

聚类算法是基于距离计算的,大数值的特征会把小数值的特征的影响完全掩盖。所以咱得先把两个数据集放到同一尺度下,再进行行聚类。常用的方法有两种:

  • Z-score标准化:把每个特征转换成均值为0、方差为1的分布,适合大部分聚类场景
  • Min-Max缩放:把所有特征缩到0-1范围,适合对数值范围敏感的情况

这里我用Z-score举例子,用sklearn的StandardScaler就能搞定:

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from scipy.cluster.hierarchy import linkage, leaves_list

# 先构造两个示例数据集(你替换成自己的真实数据就行)
df_small = pd.DataFrame(np.random.uniform(0, 1, (15, 6)), columns=[f'S_{i}' for i in range(6)])
df_large = pd.DataFrame(np.random.uniform(1000, 5000, (15, 6)), columns=[f'L_{i}' for i in range(6)])

# 合并成一个完整的DataFrame(行是样本,列是两个数据集的特征)
combined_df = pd.concat([df_small, df_large], axis=1)

# 标准化所有特征,让两个数据集在同一尺度下参与聚类
scaler = StandardScaler()
scaled_data = scaler.fit_transform(combined_df)
第二步:计算行聚类的顺序

用标准化后的数据计算层次聚类,得到样本的聚类顺序,这样后面画热力图的时候就能按聚类结果排列行:

# 计算行的层次聚类链接(用ward方法最小化类内方差,效果比较好)
row_linkage = linkage(scaled_data, method='ward')
# 获取聚类后的行索引顺序
row_order = leaves_list(row_linkage)
# 把原始数据按聚类顺序重新排列
ordered_df = combined_df.iloc[row_order, :]
第三步:绘制带独立刻度的合并热力图

Seaborn的clustermap默认只能用一个颜色刻度,所以咱用matplotlib的子图来实现双刻度效果,两个子图共享y轴,各自用对应的颜色条:

# 创建画布和子图,设置宽度比例,给颜色条留位置
fig, (ax_small, ax_large, cbar_small, cbar_large) = plt.subplots(1, 4, figsize=(14, 9),
                                                                gridspec_kw={'width_ratios': [6, 6, 0.3, 0.3]})

# 绘制第一个数据集(0-1范围)的热力图
sns.heatmap(ordered_df.iloc[:, :6], ax=ax_small, cmap='viridis', cbar=False,
            yticklabels=ordered_df.index, xticklabels=df_small.columns)
ax_small.set_title('Dataset 1 (0-1 Range)')
ax_small.set_ylabel('Samples')

# 绘制第二个数据集(1000-5000范围)的热力图,隐藏y轴标签(因为和左边共享)
sns.heatmap(ordered_df.iloc[:, 6:], ax=ax_large, cmap='plasma', cbar=False,
            yticklabels=False, xticklabels=df_large.columns)
ax_large.set_title('Dataset 2 (1000-5000 Range)')

# 给两个热力图分别添加独立的颜色条
sns.colorbar(ax_small.collections[0], cax=cbar_small)
sns.colorbar(ax_large.collections[0], cax=cbar_large)

plt.tight_layout()
plt.show()
为啥要这么做?
  • 聚类用标准化后的数据:保证两个数据集的特征对聚类结果的贡献是公平的,不会被大数值碾压
  • 可视化用原始数据:保留了每个数据集的真实数值范围,独立的颜色条能清晰展示各自的分布差异
  • 共享y轴:两个热力图的行顺序完全一致,方便对比同一聚类组在两个数据集里的表现

如果你更喜欢用Seaborn的clustermap框架,也可以先跑一次clustermap得到聚类后的行顺序,再按上面的方法拆分绘制,效果是一样的。

内容的提问来源于stack exchange,提问作者MEhsan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:16:48