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

问题描述

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

SecurityFilterChainn

enter image description here

解决方法

当你这样做

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)

enter image description here

我们有Z

array([[  2.,5.,2.],[  3.,4.,[  0.,7.,3.],[  1.,8.,4.],[  6.,9.,6.]])

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

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

然后我们有 (6,9) 即 ((2,5),(1,4)))) 的 6 个元素

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

现在我们可以构建一个 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()

enter image description here

更新

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

我们可以验证

enter image description here

# 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,mask=mask)
plt.show()

enter image description here

更新 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',10: '2,5,1,4'}