Как получить поддеревья дендрограммы, сделанные scipy.cluster.hierarchy

У меня возникла путаница в отношении этого модуля (scipy.cluster.hierarchy)... и все еще есть некоторые!

Например, у нас есть следующая дендрограмма:

hierarchical clustering

Мой вопрос: как я могу извлечь цветные поддеревья (каждый из них представляет кластер) в хорошем формате, скажем, в формате SIF? Теперь код для получения сюжета выше:

import scipy
import scipy.cluster.hierarchy as sch
import matplotlib.pylab as plt

scipy.randn(100,2)

d = sch.distance.pdist(X)

Z= sch.linkage(d,method='complete')

P =sch.dendrogram(Z)

plt.savefig('plot_dendrogram.png')

T = sch.fcluster(Z, 0.5*d.max(), 'distance')
#array([4, 5, 3, 2, 2, 3, 5, 2, 2, 5, 2, 2, 2, 3, 2, 3, 2, 5, 4, 5, 2, 5, 2,
#       3, 3, 3, 1, 3, 4, 2, 2, 4, 2, 4, 3, 3, 2, 5, 5, 5, 3, 2, 2, 2, 5, 4,
#       2, 4, 2, 2, 5, 5, 1, 2, 3, 2, 2, 5, 4, 2, 5, 4, 3, 5, 4, 4, 2, 2, 2,
#       4, 2, 5, 2, 2, 3, 3, 2, 4, 5, 3, 4, 4, 2, 1, 5, 4, 2, 2, 5, 5, 2, 2,
#       5, 5, 5, 4, 3, 3, 2, 4], dtype=int32)

sch.leaders(Z,T)
# (array([190, 191, 182, 193, 194], dtype=int32),
#  array([2, 3, 1, 4,5],dtype=int32))

Итак, вывод fcluster() дает кластеризацию узлов (по их идентификаторам), а leaders() описанный здесь должен возвращать 2 массива:

  • сначала содержит узлы-лидеры кластеров, сгенерированных Z, здесь мы можем видеть, что у нас есть 5 кластеров, а также на графике

  • а второй - идентификатор этих кластеров

Итак, если эти лидеры() вернутся соответственно. L и M: L[2]=182 и M[2]=1, то кластер 1 обозначается символом node id 182, который не существует в наборе наблюдений X, в документации говорится: "... тогда это соответствует не-синглетону кластер". Но я не могу это получить...

Кроме того, я преобразовал Z в дерево с помощью sch.to_tree(Z), который вернет простой в использовании древовидный объект, который я хочу визуализировать, но какой инструмент я должен использовать в качестве графической платформы, которая управляет такими типами древовидные объекты как входы?

Ответ 1

Отвечая на часть вашего вопроса о манипуляциях с деревьями...

Как объяснено в другом ответе, вы можете прочитать координаты веток, считывая icoord и dcoord из объекта дерева. Для каждой ветки скоординированные даны слева направо.

Если вы хотите вручную построить дерево, вы можете использовать что-то вроде:

def plot_tree(P, pos=None):
    plt.clf()
    icoord = scipy.array(P['icoord'])
    dcoord = scipy.array(P['dcoord'])
    color_list = scipy.array(P['color_list'])
    xmin, xmax = icoord.min(), icoord.max()
    ymin, ymax = dcoord.min(), dcoord.max()
    if pos:
        icoord = icoord[pos]
        dcoord = dcoord[pos]
        color_list = color_list[pos]
    for xs, ys, color in zip(icoord, dcoord, color_list):
        plt.plot(xs, ys, color)
    plt.xlim(xmin-10, xmax + 0.1*abs(xmax))
    plt.ylim(ymin, ymax + 0.1*abs(ymax))
    plt.show()

Где в вашем коде plot_tree(P) дает:

enter image description here

Функция позволяет выбрать только несколько веток:

plot_tree(P, range(10))

enter image description here

Теперь вы должны знать, какие ветки построить. Может быть, fcluster() немного неясен, и другой способ найти, какие ветки построить на основе минимального и максимального допуска на расстояние, - это напрямую использовать вывод linkage() (Z в случае OP):

dmin = 0.2
dmax = 0.3
pos = scipy.all( (Z[:,2] >= dmin, Z[:,2] <= dmax), axis=0 ).nonzero()
plot_tree( P, pos )

Рекомендуемые ссылки: