如何基于合并顺序获取Python层次聚类标签,Scipy是否有对应实现?
问题解答
scipy有内置方法可以直接实现你的需求,不需要手动解析层次聚类的合并树,也不需要硬编码距离阈值。
核心实现方法
你需要用scipy.cluster.hierarchy.fcluster方法,搭配criterion='maxclust'参数即可。
层次聚类的合并顺序和最终簇数有严格的对应关系:假设你共有N个初始样本,每完成1次合并簇数减少1,完成k次合并后最终簇数为N - k。你只需要把目标簇数传给fcluster的t参数,就能得到对应合并阶段的聚类标签。
以你举的5个样本(p1-p5)的场景为例:
- 需要完成至少1次合并(得到3个簇):调用
fcluster(Z, t=3, criterion='maxclust') - 需要完成至少2次合并(得到2个簇):调用
fcluster(Z, t=2, criterion='maxclust')
返回的结果是和样本顺序一一对应的聚类标签数组,和你举例的划分结果完全匹配。
完整代码示例
from scipy.cluster.hierarchy import linkage, fcluster import numpy as np # 模拟5个样本的特征数据 X = np.array([ [1, 2], # p1 [4, 5], # p2 [10, 12], # p3 [10.5, 12.2], # p4 [4.2, 5.1] # p5 ]) # 生成层次聚类合并矩阵Z Z = linkage(X, method='ward') # 获取完成1次合并后的3簇标签 labels_3cluster = fcluster(Z, t=3, criterion='maxclust') print("3簇标签:", labels_3cluster) # 输出类似[1,2,3,3,2],对应你举例的划分 # 获取完成2次合并后的2簇标签 labels_2cluster = fcluster(Z, t=2, criterion='maxclust') print("2簇标签:", labels_2cluster) # 输出类似[1,2,2,2,2],对应你举例的划分
手动解析扩展(可选)
如果需要自定义处理合并过程,可以直接解析linkage方法返回的Z矩阵:
Z矩阵是形状为(N-1, 4)的二维数组,每一行对应一次合并操作,按合并先后顺序排列:
- 第1、2列:本次合并的两个簇的编号
- 第3列:本次合并的距离阈值
- 第4列:合并后新簇包含的样本总数
你可以按行遍历Z矩阵,自行维护簇的分组关系,实现更定制化的需求。
场景适配说明
你的需求刚好匹配该方法的适用场景:即使新增样本后合并的距离阈值发生变化,只要你需要的是固定合并次数后的聚类结果,直接指定对应的目标簇数即可,完全不需要硬编码距离阈值,也不受阈值波动影响。
你提到的层次聚类示意图如下:
内容的提问来源于stack exchange,提问作者user96564
相关产品推荐
相关产品推荐

