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

如何获取Scipy树状图中对应样本的叶节点坐标?

Scipy层次聚类树状图:仅提取样本标签对应的节点坐标

问题背景

使用Scipy绘制层次聚类树状图的代码如下:

from scipy.cluster.hierarchy import linkage, dendrogram, complete, to_tree
from scipy.spatial.distance import squareform
import numpy as np
import pandas as pd

diff_matrix = [[0, 0, 1, 0, 1],
               [0, 0, 1, 0, 1],
               [1, 1, 0, 1, 2],
               [0, 0, 1, 0, 1],
               [1, 1, 2, 1, 0]]

linkage_matrix = linkage(squareform(diff_matrix),'complete')
dendrogram_info = dendrogram(linkage_matrix, labels= list(df.index))

执行后生成的dendrogram_info字典为:

{
    'icoord': [[35.0, 35.0, 45.0, 45.0],
               [25.0, 25.0, 40.0, 40.0],
               [15.0, 15.0, 32.5, 32.5],
               [5.0, 5.0, 23.75, 23.75]],
    'dcoord': [[0.0, 0.0, 0.0, 0.0],
               [0.0, 0.0, 0.0, 0.0],
               [0.0, 1.0, 1.0, 0.0],
               [0.0, 2.0, 2.0, 1.0]],
    'ivl': ['Sample05', 'Sample03', 'Sample04', 'Sample01', 'Sample02'],
    'leaves': [4, 2, 3, 0, 1],
    'color_list': ['C1', 'C1', 'C1', 'C0'],
    'leaves_color_list': ['C0', 'C1', 'C1', 'C1', 'C1']
}

尝试的提取代码及问题

尝试用以下代码提取样本对应的节点坐标:

leaf_coords = []
for x, y in zip(dendrogram_info['icoord'], dendrogram_info['dcoord']):
    if y[0]==0:
        leaf_coords.append([x[0], y[0]])
    if y[3]==0:
        leaf_coords.append([x[3], y[3]])

得到的结果包含[40.0, 0]、[32.5, 0]这类非样本节点坐标:

[[35.0, 0.0],
 [45.0, 0.0],
 [25.0, 0.0],
 [40.0, 0.0],
 [15.0, 0.0],
 [32.5, 0.0],
 [5.0, 0.0]]

需要仅提取下图中箭头所示的样本/标签对应的节点坐标:
Scipy层次聚类树状图

解决方案

方法1:过滤去重并排序

通过记录已出现的x坐标,避免重复添加中间节点的坐标,最终排序得到样本节点坐标:

leaf_coords = []
seen_x = set()
for x_vals, y_vals in zip(dendrogram_info['icoord'], dendrogram_info['dcoord']):
    # 遍历线段的所有端点,收集y=0且未记录过的x坐标
    for x, y in zip(x_vals, y_vals):
        if y == 0.0 and x not in seen_x:
            leaf_coords.append([x, y])
            seen_x.add(x)
# 按x坐标排序,对应标签的显示顺序
leaf_coords.sort()

执行后得到的结果为:

[[5.0, 0.0], [15.0, 0.0], [25.0, 0.0], [35.0, 0.0], [45.0, 0.0]]

方法2:利用标签顺序直接生成

Scipy的dendrogram默认叶子节点的x坐标按固定间隔排列(从5开始,每次递增10),可直接根据标签列表长度生成:

# 按ivl中的标签顺序生成对应坐标
leaf_coords = [[5 + 10*i, 0.0] for i in range(len(dendrogram_info['ivl']))]

如需将坐标与样本标签关联,可生成字典:

coords_dict = {label: [5 + 10*i, 0.0] for i, label in enumerate(dendrogram_info['ivl'])}

说明

之前的代码会捕获中间合并节点的端点,是因为这些节点的线段也存在y=0的端点,但它们不属于样本叶子节点。通过记录已出现的x坐标,可有效过滤掉这类非样本节点;而利用固定间隔生成的方式更简洁,适合默认布局的场景。

内容的提问来源于stack exchange,提问作者崔箐坡

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 19:04:57