如何在python中提取树状图中点之间的距离?

Posted

技术标签:

【中文标题】如何在python中提取树状图中点之间的距离?【英文标题】:How can I extract the distances between points within a dendogram in python? 【发布时间】:2021-06-27 06:25:59 【问题描述】:

我在 python 中执行层次聚类并获得了树状图。我想知道是否有一种方法可以提取最近点之间的距离,例如这里:7 到 8 之间的距离(最近的一个),然后是 0 到 1 之间的距离等等,为了生成绘图,我使用了函数:

linkage_matrix= linkage(dfP, method="single") 

cluster_dict = dendrogram (linkage_matrix)

【问题讨论】:

请提供您的dfP 【参考方案1】:

当你这样做时

Z = hierarchy.linkage(X, method='single')

Z 矩阵中,您拥有所需的一切:cluster1、cluster2、距离、集群中的元素数量。

例如

import numpy as np
import pandas as pd
from scipy.cluster import hierarchy
import matplotlib.pyplot as plt
import seaborn as sns
X = np.array([662., 877., 255., 412., 996., 295., 468., 268.,
                   400., 754., 564., 138., 219., 869., 669.])

Z = hierarchy.linkage(X, method='single')
plt.figure()
dn = hierarchy.dendrogram(Z)

我们有Z

array([[  2.,   5., 138.,   2.],
       [  3.,   4., 219.,   2.],
       [  0.,   7., 255.,   3.],
       [  1.,   8., 268.,   4.],
       [  6.,   9., 295.,   6.]])

因为我们只有 6 个元素,所以 0 到 5 是单个元素,从 6 开始它们是元素簇

6 是 2 个元素的第一个簇 (2,5) 7 是 2 个元素的第二个簇 (3,4) 8 是第三个簇 (0,7),即 (0,(3,4)) 的 3 个元素 9 是第四个簇 (1,8),即 4 个元素的 (1,(0,(3,4)))

那么我们有 (6,9) 即 ((2,5),(1,(0,(3,4)))) 的 6 个元素

clusters = 
    0: '0',
    1: '1',
    2: '2',
    3: '3',
    4: '4',
    5: '5',
    6: '2,5',
    7: '3,4',
    8: '0,3,4',
    9: '1,0,3,4',

现在我们可以构建一个df 来显示热图

# init the DataFrame
df = pd.DataFrame(
    columns=Z[:,0].astype(int), 
    index=Z[:,1].astype(int)
)

df.columns = df.columns.map(clusters)
df.index = df.index.map(clusters)

# populate the diagonal
for i, d in enumerate(Z[:,2]):
    df.iloc[i, i] = d

# fill NaN
df.fillna(0, inplace=True)
# mask everything but diagonal
mask = np.ones(df.shape, dtype=bool)
np.fill_diagonal(mask, 0)

# plot the heatmap
sns.heatmap(df, 
            annot=True, fmt='.0f', cmap="YlGnBu", 
            mask=mask)
plt.show()

更新

我将X 定义为距离数组。这些是元素之间的距离的幂零下三角矩阵的值,按列。

我们可以验证

# number of elements
n = (np.sqrt(8 * X.size + 1) + 1) / 2
n
6.0

我们有 n=6 元素,这是距离的幂零下三角矩阵

# init the DataFrame
df = pd.DataFrame(columns=range(int(n)), index=range(int(n)))
# populate the DataFrame
idx = 0
for c in range(int(n)-1):
    for r in range(c+1, int(n)):
        df.iloc[r, c] = X[idx]
        idx += 1
# fill NaNs and mask
df.fillna(0, inplace=True)
mask = np.zeros_like(df)
mask[np.triu_indices_from(mask)] = True
# plot the matrix
sns.heatmap(df, annot=True, fmt='.0f', cmap="YlGnBu", mask=mask)
plt.show()

更新 2

如何为集群距离对角矩阵自动填充地图字典。

首先我们必须计算元素的数量(仅当X 是距离数组时才需要),正如我们之前看到的那样

# number of elements
n = (np.sqrt(8 * X.size + 1) + 1) / 2

然后,我们可以循环遍历Z 矩阵来填充字典

# clusters of single elements
clusters = i: str(i) for i in range(int(n))
# loop through Z matrix
for i, z in enumerate(Z.astype(int)):
    # cluster number
    cluster_num = int(n+i)
    # elements in clusters
    cluster_names = [clusters[z[0]], clusters[z[1]]]
    cluster_elements = [str(i) for i in cluster_names]
    # update the dictionary
    clusters.update(cluster_num: ','.join(cluster_elements))

我们有

clusters

0: '0',
 1: '1',
 2: '2',
 3: '3',
 4: '4',
 5: '5',
 6: '2,5',
 7: '3,4',
 8: '0,3,4',
 9: '1,0,3,4',
 10: '2,5,1,0,3,4'

【讨论】:

非常感谢!是的,dfP 是一个距离矩阵。 YVW,我添加了元素之间的距离矩阵,以备不时之需 再次感谢,这真的很清楚@MaxPierini 抱歉,最后一个问题,如何创建制作热图所需的集群字典? @MaxPierini 我更新了一种填充字典的方法

以上是关于如何在python中提取树状图中点之间的距离?的主要内容,如果未能解决你的问题,请参考以下文章

从 R 中的切割树状图中提取标签成员资格/分类(即:树状图的 cutree 函数)

如何使用 Python 从导入的 csv 计算纬度/经度点之间的距离?

Python使用matplotlib可视化树状图层次聚类系统树图树状图根据给定的距离度量将相似点分组在一起并根据点的相似性将它们组织成树状图链接起来(Dendrogram)

如何从 XY 散点图中删除异常值

如何仅使用 numpy 从距离矩阵中提取数据点?

如何计算一个python函数来计算/绘制点和曲线之间的最小距离?