Пользовательские кластера цветами составляющей дендрограмма в Python (ссылка цвет Функ?)

Я хочу раскрасить свои кластеры цветовой картой, которую я сделал в виде словаря (т. е. {leaf: color}).

Я пробовал следовать https://joernhees.de/blog/2015/08/26/scipy-hierarchical-clustering-and-dendrogram-tutorial/ но цвета почему-то перепутались. Сюжет по умолчанию выглядит хорошо, я просто хочу назначить эти цвета по-разному. Я видел, что там был link_color_func но когда я попытался использовать свою цветовую карту (D_leaf_color словарь) я получил ошибку b/c это не функция. Я создал D_leaf_color для настройки цветов листьев, связанных с определенными кластерами. В моем фактическом наборе данных цвета что-то означают, поэтому я избегаю произвольных цветовых назначений.

Я не хочу использовать color_threshold b/c в моих фактических данных у меня больше кластеров и SciPy повторяет цвета, следовательно, этот вопрос. . .

как я могу использовать свой словарь цвета листа для настройки цвета моей дендрограммы кластеры?

Я сделал выпуск GitHub https://github.com/scipy/scipy/issues/6346 где я более подробно остановился на подходе к окраске листьев в интерпретация вывода дендрограммы иерархической кластеризации SciPy? (возможно, нашел ошибку...) но я все еще не могу понять, как на самом деле: (i) использовать вывод дендрограммы для восстановления моей дендрограммы с помощью моего указанного цветового словаря или (ii) переформатировать мой D_leaf_color словарь для

3 ответов


здесь решение, которое использует возвращаемую матрицу Z of linkage() (описано рано, но немного скрыто в docs) и link_color_func:

# see question for code prior to "color mapping"

# Color mapping
dflt_col = "#808080"   # Unclustered gray
D_leaf_colors = {"attr_1": dflt_col,

                 "attr_4": "#B061FF", # Cluster 1 indigo
                 "attr_5": "#B061FF",
                 "attr_2": "#B061FF",
                 "attr_8": "#B061FF",
                 "attr_6": "#B061FF",
                 "attr_7": "#B061FF",

                 "attr_0": "#61ffff", # Cluster 2 cyan
                 "attr_3": "#61ffff",
                 "attr_9": "#61ffff",
                 }

# notes:
# * rows in Z correspond to "inverted U" links that connect clusters
# * rows are ordered by increasing distance
# * if the colors of the connected clusters match, use that color for link
link_cols = {}
for i, i12 in enumerate(Z[:,:2].astype(int)):
  c1, c2 = (link_cols[x] if x > len(Z) else D_leaf_colors["attr_%d"%x]
    for x in i12)
  link_cols[i+1+len(Z)] = c1 if c1 == c2 else dflt_col

# Dendrogram
D = dendrogram(Z=Z, labels=DF_dism.index, color_threshold=None,
  leaf_font_size=12, leaf_rotation=45, link_color_func=lambda x: link_cols[x])
выход: dendrogram

Two-liner для применения пользовательской цветовой карты к ветвям кластера:

import matplotlib as mpl
from matplotlib.pyplot import cm
from scipy.cluster import hierarchy

cmap = cm.rainbow(np.linspace(0, 1, 10))
hierarchy.set_link_color_palette([mpl.colors.rgb2hex(rgb[:3]) for rgb in cmap])

затем вы можете заменить Радужный любым cmap и измените 10 для номера кластера, который вы хотите.


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

# Init
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()

# Load data
from sklearn.datasets import load_diabetes

# Clustering
from scipy.cluster.hierarchy import dendrogram, fcluster, leaves_list, set_link_color_palette
from scipy.spatial import distance
from fastcluster import linkage # You can use SciPy one too

%matplotlib inline
# Dataset
A_data = load_diabetes().data
DF_diabetes = pd.DataFrame(A_data, columns = ["attr_%d" % j for j in range(A_data.shape[1])])

# Absolute value of correlation matrix, then subtract from 1 for disimilarity
DF_dism = 1 - np.abs(DF_diabetes.corr())

# Compute average linkage
A_dist = distance.squareform(DF_dism.as_matrix())
Z = linkage(A_dist,method="average")

# Color mapping dict not relevant in this case
# Dendrogram
# To get this dendrogram coloring below  `color_threshold=0.7`
#Change the color palette, I did not include the grey, which is used above the threshold
set_link_color_palette(["#B061FF", "#61ffff"])
D = dendrogram(Z=Z, labels=DF_dism.index, color_threshold=.7, leaf_font_size=12, leaf_rotation=45, 
               above_threshold_color="grey")

результат:

enter image description here