Python获取聚类数据-层次聚类

1 投票
1 回答
2191 浏览
提问于 2025-04-18 07:32

我用下面的Python脚本做了层次聚类,并打印出了树状图。请注意,我对数据挖掘还很陌生。

import numpy as np
import distance
import scipy.cluster.hierarchy
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import dendrogram, linkage

mat = np.array([[ 0. , 1. , 3.  ,0. ,2.  ,3.  ,1.],
 [ 1. , 0. , 3. , 1.,  1. , 2. , 2.],
 [ 3.,  3. , 0.,  3. , 3.,  3. , 4.],
 [ 0. , 1. , 3.,  0. , 2. , 3.,  1.],
 [ 2. , 1.,  3. , 2.,  0. , 1.,  3.],
 [ 3. , 2.,  3. , 3. , 1. , 0. , 3.],
 [ 1. , 2.,  4. , 1. , 3.,  3. , 0.]])

linkage_matrix = linkage(mat, "single")

dendrogram(linkage_matrix,
           color_threshold=1,
           truncate_mode='lastp',
           distance_sort='ascending')

plt.show()

下面是我得到的树状图。我想打印出每个聚类以及属于每个聚类的数据,应该怎么做呢?

cluster1 4,5
cluster2 ..,..
cluster3 ..,..

在这里输入图片描述

1 个回答

3

根据 scipy.cluster.hierarchy 的文档

(通过运行 linkage...)会返回一个 4 行 (n-1) 列的矩阵 Z。在第 i 次迭代中,索引为 Z[i, 0] 和 Z[i, 1] 的聚类会被合并成一个新的聚类 n + i。索引小于 n 的聚类对应于 n 个原始观测值中的一个。Z[i, 2] 给出了聚类 Z[i, 0] 和 Z[i, 1] 之间的距离。第四个值 Z[i, 3] 表示新形成的聚类中包含的原始观测值的数量。

这意味着,我们可以遍历 linkage_matrix,找到实际合并形成新聚类的节点。下面是一个简单的 for 循环来实现这个功能

n = len(mat)
cluster_dict = dict()
for i in range(0, 6):
    new_cluster_id = n+i
    old_cluster_id_0 = linkage_matrix[i, 0]
    old_cluster_id_1 = linkage_matrix[i, 1]
    combined_ids = list()
    if old_cluster_id_0 in cluster_dict:
        combined_ids += cluster_dict[old_cluster_id_0]
        del cluster_dict[old_cluster_id_0]
    else:
        combined_ids += [old_cluster_id_0]
    if old_cluster_id_1 in cluster_dict:
        combined_ids += cluster_dict[old_cluster_id_1]
        del cluster_dict[old_cluster_id_1]
    else:
        combined_ids += [old_cluster_id_1]
    cluster_dict[new_cluster_id] = combined_ids
    print cluster_dict

这段代码创建了一个字典,用于存储聚类 ID 和该聚类中包含的节点。在每次迭代中,它将 linkage_matrix[i, 0]linkage_matrix[i, 1] 中的两个节点合并成一个新节点。最后,它会打印出每次迭代中正在运行的聚类。输出结果是

{7: [0.0, 3.0]}
{8: [4.0, 5.0], 7: [0.0, 3.0]}
{8: [4.0, 5.0], 9: [6.0, 0.0, 3.0]}
{8: [4.0, 5.0], 10: [1.0, 6.0, 0.0, 3.0]}
{11: [4.0, 5.0, 1.0, 6.0, 0.0, 3.0]}
{12: [2.0, 4.0, 5.0, 1.0, 6.0, 0.0, 3.0]}

(聚类 ID 从 7 开始,原始行的索引是 0 到 6)。注意,字典中没有的 ID 会形成自己的聚类。例如,行 2.0 在第 2 次迭代中形成了自己的聚类。你可以根据自己的停止标准,提前停止,从而得到最终的聚类集合。

我可以在第 3 次迭代时停止(输出的第 3 行),然后我的聚类将是:

cluster 8: {4, 5}
cluster 9: {6, 0, 3}
cluster 1: {1}
cluster 2: {2}

撰写回答