J'utilise le seaborn clustermap
pour créer des clusters et visuellement cela fonctionne très bien (cela exemple produit des résultats très similaires).
Cependant, j'ai du mal à trouver comment extraire par programme les clusters. Par exemple, dans l'exemple de lien, comment pourrais-je savoir que 1-1 rh, 1-1 lh, 5-1 rh, 5-1 lh font un bon cluster? Visuellement, c'est facile. J'essaie d'utiliser des méthodes de recherche dans les données et des dendrogrammes mais j'ai peu de succès
[~ # ~] éditez [~ # ~] Code de l'exemple:
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)
Comment puis-je extraire les modèles dans quels clusters de result
?
EDIT2 Le result
porte avec lui un linkage
avec le dendrogram_col
avec lequel je PENSE que je travaillerais avec fcluster . Mais la valeur seuil à sélectionner qui me déroute. Je suppose que les valeurs de la carte thermique qui sont supérieures au seuil seraient regroupées?
En utilisant result.linkage.dendrogram_col
ou result.linkage.dendrogram_row
fonctionnera actuellement, il semble que ce soit un détail d'implémentation. La route la plus sûre consiste à calculer d'abord les liens de manière explicite et à les transmettre à la fonction clustermap
, qui a row_linkage
et col_linkage
paramètres juste pour ça.
Remplacement de la dernière ligne de votre exemple (result =
...) avec le code suivant donne le même résultat qu'auparavant, mais vous aurez également row_linkage
et col_linkage
variables que vous pouvez utiliser avec fcluster
etc.
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)
Dans cet exemple particulier, le code pourrait être simplifié davantage car le tableau de corrélations est symétrique et donc row_linkage
et col_linkage
sera identique.
Remarque: Une réponse précédente comprenait un appel à distance.squareshape
selon ce que fait le code dans seaborn, mais cela est un bug .
Vous souhaitez probablement une nouvelle colonne dans votre trame de données avec l'appartenance au cluster. J'ai réussi à le faire à partir d'extraits de code assemblés volés sur le Web:
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
Cela vous donne donc une colonne avec "g" ou "r" pour les grappes étiquetées en vert ou en rouge. Je détermine mon seuil de couleur en traçant le dendrogramme et en observant les valeurs de l'axe y.