前阵子处理一批群落数据,87个样本,想按组成相似度分组。当时我第一反应就是打开Matlab,先 pdist 再 linkage,最后 dendrogram 出一张树状图收工。结果内部复核时发现:同样的数据、同样的欧氏距离,用 WPGMA 和UPGMA跑出来的树状图并不完全一样,分支高度明显偏离。就是从那次之后,我把层次聚类从“调用两个内置函数”重新梳理成了“彻底搞清楚每一步合并到底在算什么”。
这篇就把这段时间梳理清楚的内容写出来:层次聚类里最常用的 WPGMA 和 UPGMA 到底如何工作、为什么一个叫加权一个叫未加权、树状图怎么读,以及一套能直接复制到 Matlab 里跑的完整代码。尤其适合生物信息、生态学、市场细分这类需要反复解释聚类过程、却不能只丢一句“算法自动完成”的场景。
1. 层次聚类的核心不是代码,而是距离矩阵如何不断“合并”
很多人一上来就盯住 “linkage”“dendrogram” 这些函数,但我建议先把整条链路拆开。层次聚类不是靠某个“智能判断”直接把人分组,它实际做的事情非常朴素:先定义两个样本怎么算相似,再不断把最相似的两个东西合并到一起,直到所有样本都收进同一个大类。整个过程如果不用编程语言,用纸笔也能完成,只不过样本少时可以手算,样本多时交给计算机。
1.1 样本距离定义是第一步
无论你选 UPGMA、WPGMA 还是别的方法,第一步永远是构造样本之间的距离。Matlab 里最常用的是 pdist,默认算的是欧氏距离:
matlab复制Y = pdist(X); % X 是 n 行、d 列的矩阵
这里容易忽略一个关键点:距离度量直接决定了后续所有合并的“高度”,换一种距离,树状图基本就会换一张脸。常见的选择有:
- 欧氏距离:适用于各列变量单位一致、数值分布范围接近的数据。如果身高、体重、收入这种量纲完全不同的列混在一起,不建议直接用默认欧氏距离,必须先标准化。
- 曼哈顿距离:对高维稀疏数据有时更好用。
- 相关距离:
pdist(X, 'correlation')返回1 - Pearson相关系数。基因表达谱这类数据经常用它,因为研究者更关心样本反应的“形状”是否一致,而不是绝对表达量差多少。 - 余弦距离:文本向量、用户偏好向量常用。
这里
