12

Ich verwende die seaborn clustermap Cluster zu erstellen und visuell funktioniert es gut (diese example produziert sehr ähnliche Ergebnisse).Extrahieren von Clustern von Seaborn Clustermap

Allerdings habe ich Probleme herauszufinden, wie Sie die Cluster programmgesteuert extrahieren. Wie könnte ich zum Beispiel im Beispiel-Link herausfinden, dass 1-1 rh, 1-1 lh, 5-1 rh, 5-1 lh einen guten Cluster bilden? Visuell ist es einfach. Ich versuche, Methoden des Blicks durch die Daten zu verwenden, und Dendrogramme aber ich habe wenig Erfolg

EDIT-Code aus Beispiel:

import pandas as pd 
import seaborn as sns 
sns.set(font="monospace") 

df = sns.load_dataset("brain_networks", header=[0, 1, 2], index_col=0) 
used_networks = [1, 5, 6, 7, 8, 11, 12, 13, 16, 17] 
used_columns = (df.columns.get_level_values("network") 
          .astype(int) 
          .isin(used_networks)) 
df = df.loc[:, used_columns] 

network_pal = sns.cubehelix_palette(len(used_networks), 
            light=.9, dark=.1, reverse=True, 
            start=1, rot=-2) 
network_lut = dict(zip(map(str, used_networks), network_pal)) 

networks = df.columns.get_level_values("network") 
network_colors = pd.Series(networks).map(network_lut) 

cmap = sns.diverging_palette(h_neg=210, h_pos=350, s=90, l=30, as_cmap=True) 

result = sns.clustermap(df.corr(), row_colors=network_colors, method="average", 
       col_colors=network_colors, figsize=(13, 13), cmap=cmap) 

Wie kann ich ziehen, welche Modelle sind in welchen Cluster aus von result?

EDIT2 Die result hat mit ihm trägt ein linkage in den dendrogram_col, die ich mit fcluster funktionieren würde denken. Aber der Schwellwert zur Auswahl, der mich verwirrt. Ich würde annehmen, dass Werte in der Heatmap, die höher als der Schwellenwert sind, zusammen gruppiert werden würden?

Antwort

10

Während der Verwendung von result.linkage.dendrogram_col oder result.linkage.dendrogram_row derzeit funktioniert, scheint es ein Implementierungsdetail zu sein. Der sicherste Weg besteht darin, die Verknüpfungen zuerst explizit zu berechnen und sie an die clustermap-Funktion zu übergeben, die row_linkage und col_linkage Parameter nur dafür hat.

die letzte Zeile in Ihrem Beispiel Ersetzen (result = ...) mit dem folgenden Code das gleiche Ergebnis wie zuvor, aber Sie werden auch row_linkage und col_linkage Variablen haben, die Sie mit fcluster usw. verwenden können

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

correlations = df.corr() 
correlations_array = np.asarray(df.corr()) 

row_linkage = hierarchy.linkage(
    distance.pdist(correlations_array), method='average') 

col_linkage = hierarchy.linkage(
    distance.pdist(correlations_array.T), method='average') 

sns.clustermap(correlations, row_linkage=row_linkage, col_linkage=col_linkage, row_colors=network_colors, method="average", 
       col_colors=network_colors, figsize=(13, 13), cmap=cmap) 

In diesem speziellen Beispiel könnte der Code mehr vereinfacht werden, da das Korrelationsarray symmetrisch ist und daher row_linkage und col_linkage identisch sind.

Hinweis: Eine vorherige Antwort einen Aufruf an distance.squareshape enthielt je nachdem, was der Code in Seaborn tut, aber die is a bug.

+0

Hey @Marcel M, möchten Sie nicht eine "Unähnlichkeitsmatrix" anstelle einer Korrelationsmatrix verwenden? Wie '1 - np.abs (Korrelationen)' oder etwas? –

+1

@ O.rka Das Übergeben von Korrelationen an "sns.clustermap()" kommt von dem Seaborn-Beispiel, das in der Frage zitiert wird, die ich gerade kopiert habe. Beide Versionen berechnen Distanzen zwischen Korrelationen, also werden am Ende tatsächlich Distanzen verwendet, aber ich gebe zu, ich weiß nicht, wie viel Sinn es dazu macht (ich weiß nicht, warum das Seaborn-Beispiel so ist). In meinem eigenen Projekt verwende ich Entfernungen direkt. –

3

Sie möchten wahrscheinlich eine neue Spalte in Ihrem Datenrahmen mit der Cluster-Mitgliedschaft. Ich habe es geschafft, aus der ganzen Bahn gestohlen diese aus zusammengesetzten Code-Schnipsel zu tun:

import seaborn 
import scipy 

g = seaborn.clustermap(df,method='average') 
den = scipy.cluster.hierarchy.dendrogram(g.dendrogram_col.linkage, 
             labels = df.index, 
             color_threshold=0.60) 
from collections import defaultdict 

def get_cluster_classes(den, label='ivl'): 
    cluster_idxs = defaultdict(list) 
    for c, pi in zip(den['color_list'], den['icoord']): 
     for leg in pi[1:3]: 
      i = (leg - 5.0)/10.0 
      if abs(i - int(i)) < 1e-5: 
       cluster_idxs[c].append(int(i)) 

    cluster_classes = {} 
    for c, l in cluster_idxs.items(): 
     i_l = [den[label][i] for i in l] 
     cluster_classes[c] = i_l 

    return cluster_classes 

clusters = get_cluster_classes(den) 

cluster = [] 
for i in df.index: 
    included=False 
    for j in clusters.keys(): 
     if i in clusters[j]: 
      cluster.append(j) 
      included=True 
    if not included: 
     cluster.append(None) 

df["cluster"] = cluster 

So erhalten Sie so eine Spalte mit ‚g‘ oder ‚r‘ für die grün- oder rot-markierten Clustern. Ich ermittle meinen color_threshold, indem ich das dendrogram zeichne und die y-axis Werte ansehe.

+0

Dies funktioniert nicht bei größeren Daten, bei denen es sich um mehr Gruppen als Farben handelt, da (zum Beispiel) Grün sich wiederholt, so dass Farben gruppiert werden. – PvdL