如何提取 python 中树状图中各点之间的距离?
How can I extract the distances between points within a dendogram in python?
我在 python 中执行层次聚类并获得了树状图。我想知道是否有一种方法可以提取最近点之间的距离,例如:7 和 8 之间的距离(最近的距离),然后是 0 和 1 之间的距离,依此类推,为了生成绘图,我使用了函数:
linkage_matrix= linkage(dfP, method="single")
cluster_dict = dendrogram (linkage_matrix)
当你这样做时
Z = hierarchy.linkage(X, method='single')
在 Z
矩阵中,您拥有所需的一切:簇 1、簇 2、距离、簇中元素的数量。
例如
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),即3个元素的(0,(3,4))
- 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'}
我在 python 中执行层次聚类并获得了树状图。我想知道是否有一种方法可以提取最近点之间的距离,例如:7 和 8 之间的距离(最近的距离),然后是 0 和 1 之间的距离,依此类推,为了生成绘图,我使用了函数:
linkage_matrix= linkage(dfP, method="single")
cluster_dict = dendrogram (linkage_matrix)
当你这样做时
Z = hierarchy.linkage(X, method='single')
在 Z
矩阵中,您拥有所需的一切:簇 1、簇 2、距离、簇中元素的数量。
例如
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),即3个元素的(0,(3,4))
- 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'}