Отображение меток кластеров для дендрограммы scipy

Я использую иерархическую кластеризацию для кластеризации векторов слов и хочу, чтобы пользователь мог отображать дендрограмму, показывающую кластеры. Однако, поскольку могут быть тысячи слов, я хочу, чтобы эта дендрограмма была усечена до некоторого разумного значения, а метка для каждого листа представляла собой строку наиболее значимых слов в этом кластере.

Моя проблема в том, что согласно документам, "Значение labels[i] – это текст, который следует поместить под i-м конечным узлом, только если он соответствует исходному наблюдению, а не неодноэлементному кластеру." Я понимаю, что это означает Я не могу маркировать кластеры, только особые точки?

Чтобы проиллюстрировать это, вот короткий скрипт на Python, который генерирует простую маркированную дендрограмму:

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

randomMatrix = np.random.uniform(-10,10,size=(20,3))
linked = linkage(randomMatrix, 'ward')

labelList = ["foo" for i in range(0, 20)]

plt.figure(figsize=(15, 12))
dendrogram(
            linked,
            orientation='right',
            labels=labelList,
            distance_sort='descending',
            show_leaf_counts=False
          )
plt.show()

дендрограмма случайно сгенерированных точек

Теперь предположим, что я хочу обрезать до 5 листьев, и для каждого листа пометить его как "foo, foo, foo...", т.е. слова, которые составляют этот кластер. (Примечание: создание этих меток здесь не проблема.) Я усекаю его и предоставляю соответствующий список меток:

labelList = ["foo, foo, foo..." for i in range(0, 5)]
dendrogram(
            linked,
            orientation='right',
            p=5,
            truncate_mode='lastp',
            labels=labelList,
            distance_sort='descending',
            show_leaf_counts=False
          )

и вот проблема, нет меток:

введите описание изображения здесь

Я думаю, что здесь может быть использован параметр «leaf_label_func», но я не уверен, как его использовать.


person EmmetOT    schedule 08.03.2016    source источник
comment
Я опоздал на вечеринку на пару лет, но причина отсутствия меток в том, что параметр метки для дендрограммы работает только для одноэлементных кластеров. Non singleton требуют более сложного подхода   -  person Yuca    schedule 03.07.2018


Ответы (2)


Вы правы в использовании параметра leaf_label_func.

Помимо создания графика, функция дендрограммы возвращает словарь (в документах он называется R), содержащий несколько списков. Создаваемая вами функция leaf_label_func должна принимать значение из R["leaves"] и возвращать желаемую метку. Самый простой способ установить метки — дважды запустить дендрограмму. Один раз с no_plot=True, чтобы словарь использовался для создания вашей карты меток. А потом снова создавать сюжет.

randomMatrix = np.random.uniform(-10,10,size=(20,3))
linked = linkage(randomMatrix, 'ward')

labels = ["A", "B", "C", "D"]
p = len(labels)

plt.figure(figsize=(8,4))
plt.title('Hierarchical Clustering Dendrogram (truncated)', fontsize=20)
plt.xlabel('Look at my fancy labels!', fontsize=16)
plt.ylabel('distance', fontsize=16)

# call dendrogram to get the returned dictionary 
# (plotting parameters can be ignored at this point)
R = dendrogram(
                linked,
                truncate_mode='lastp',  # show only the last p merged clusters
                p=p,  # show only the last p merged clusters
                no_plot=True,
                )

print("values passed to leaf_label_func\nleaves : ", R["leaves"])

# create a label dictionary
temp = {R["leaves"][ii]: labels[ii] for ii in range(len(R["leaves"]))}
def llf(xx):
    return "{} - custom label!".format(temp[xx])

## This version gives you your label AND the count
# temp = {R["leaves"][ii]:(labels[ii], R["ivl"][ii]) for ii in range(len(R["leaves"]))}
# def llf(xx):
#     return "{} - {}".format(*temp[xx])


dendrogram(
            linked,
            truncate_mode='lastp',  # show only the last p merged clusters
            p=p,  # show only the last p merged clusters
            leaf_label_func=llf,
            leaf_rotation=60.,
            leaf_font_size=12.,
            show_contracted=True,  # to get a distribution impression in truncated branches
            )
plt.show()
person coradek    schedule 14.02.2018
comment
+1 за товарища по оцинковке квасцов. Однако знаете ли вы способ получить наблюдения, из которых состоят усеченные листья? например У меня есть 130 тыс. выборок, я усекаю 100 кластеров и хочу знать, какие наблюдения находятся в каждом кластере. - person Grr; 01.05.2019
comment
@Grr Я использую scipy.cluster.hierarchy.fcluster для получения кластеров. У Йорна Хиса есть хорошее руководство по этому вопросу по адресу joernhees.de/blog/2015/08/26/ - person coradek; 01.06.2019

вы можете просто написать:

hierarchy.dendrogram(Z, labels=label_list)

Вот хороший пример использования фрейма данных pandas:

import numpy as np
import pandas as pd
from scipy.cluster import hierarchy
import matplotlib.pyplot as plt

data = [[24, 16], [13, 4], [24, 11], [34, 18], [41, 
6], [35, 13]]
frame = pd.DataFrame(np.array(data), columns=["Rape", 
"Murder"], index=["Atlanta", "Boston", "Chicago", 
"Dallas", "Denver", "Detroit"])

Z = hierarchy.linkage(frame, 'single')
plt.figure()
dn = hierarchy.dendrogram(Z, labels=frame.index)
person Mohammad Forouhesh    schedule 19.05.2021