如何让fcluster返回与cut_tree相同的输出?

时间:2017-11-28 15:32:03

标签: python scipy cluster-analysis hierarchical-clustering

有几个相关的问题,我认为最相关的是this question

我们假设我有一个这样的数据集(为了演示目的而高度简化):

import numpy as np
import pandas as pd

from scipy.spatial import distance
from scipy.cluster import hierarchy

val = np.array([[0.20288834,   0.80406494,   4.59921579,  14.28184739],
                [0.22477082,   1.43444223,   6.87992605,  12.90299896],
                [0.22811485,   0.74509454,   3.85198421,  19.22564266],
                [0.20374529,   0.73680174,   3.63178517,  17.82544951],
                [0.22722696,   0.86113728,   3.00832186,  16.62306058],
                [0.25577882,   0.85671779,   3.70655719,  17.49690061],
                [0.23018219,   0.68039151,   2.50815837,  15.09039053],
                [0.21638751,   1.12455083,   3.56246872,  18.82866991],
                [0.26600895,   1.09415595,   2.85300018,  17.93139433],
                [0.22369445,   0.73689845,   3.24919113,  18.60914745]])

df = pd.DataFrame(val, columns=["C{}".format(i) for i in range(val.shape[1])])

         C0        C1        C2         C3
0  0.202888  0.804065  4.599216  14.281847
1  0.224771  1.434442  6.879926  12.902999
2  0.228115  0.745095  3.851984  19.225643
3  0.203745  0.736802  3.631785  17.825450
4  0.227227  0.861137  3.008322  16.623061
5  0.255779  0.856718  3.706557  17.496901
6  0.230182  0.680392  2.508158  15.090391
7  0.216388  1.124551  3.562469  18.828670
8  0.266009  1.094156  2.853000  17.931394
9  0.223694  0.736898  3.249191  18.609147

我想对此数据帧的列进行聚类,从而指定我获得的簇数。通常,这可以通过使用cut_tree function来实现。

但是,目前,cut_tree is broken因此我寻找了替代方案,这使我在本文开头的链接中建议使用fcluster作为替代方案。

问题是我没有看到如何使用maxclust参数指定确切数量的聚类,而只是指定最大数量。

因此,对于我上面的简单示例,我可以这样做:

# number of target cluster
n_clusters = range(1, 5)

for n_clust in n_clusters:
    Z = hierarchy.linkage(distance.pdist(df.T.values), method='average', metric='euclidean')

    print("--------\nValues from flcuster:\n{}".format(hierarchy.fcluster(Z, n_clust, criterion='maxclust')))
    print("\nValues from cut_tree:\n{}".format(hierarchy.cut_tree(Z, n_clust).T))

打印

Values from flcuster:
[1 1 1 1]

Values from cut_tree:
[[0 0 0 0]]
--------
Values from flcuster:
[1 1 1 2]

Values from cut_tree:
[[0 0 0 1]]
--------
Values from flcuster:
[1 1 1 2]

Values from cut_tree:
[[0 0 1 2]]
--------
Values from flcuster:
[1 1 1 2]

Values from cut_tree:
[[0 1 2 3]]

如您所见,fcluster最多返回2个不同的群集,而cut_tree则返回所需的数量。

fcluster中的错误修复之前,有没有办法让cut_tree获得相同的输出?如果没有,在另一个包中还有其他好的选择吗?

1 个答案:

答案 0 :(得分:3)

不确定如何从fcluster中获取正确数量的群集。

作为替代方案,scikit-learn有AgglomerativeClustering

from sklearn.cluster import AgglomerativeClustering

# number of target cluster
n_clusters = range(1, 5)

for n_clust in n_clusters:
    Z = hierarchy.linkage(distance.pdist(df.T.values), method='average', metric='euclidean')

    print("--------\nValues from flcuster:\n{}".format(hierarchy.fcluster(Z, n_clust, criterion='maxclust')))
    print("\nValues from cut_tree:\n{}".format(hierarchy.cut_tree(Z, n_clust).T))

    print("\nValues from AgglomerativeClustering:\n{}".format(AgglomerativeClustering(n_clusters=n_clust, affinity='euclidean', linkage='average').fit(df.T.values).labels_))

为所提供的数据集返回正确数量的聚类(尽管顺序不同):

Values from flcuster:
[1 1 1 1]

Values from cut_tree:
[[0 0 0 0]]

Values from AgglomerativeClustering:
[0 0 0 0]
--------
Values from flcuster:
[1 1 1 2]

Values from cut_tree:
[[0 0 0 1]]

Values from AgglomerativeClustering:
[0 0 0 1]
--------
Values from flcuster:
[1 1 1 2]

Values from cut_tree:
[[0 0 1 2]]

Values from AgglomerativeClustering:
[0 0 2 1]
--------
Values from flcuster:
[1 1 1 2]

Values from cut_tree:
[[0 1 2 3]]

Values from AgglomerativeClustering:
[3 1 2 0]