web-dev-qa-db-ja.com

Seabornクラスターマップからクラスターを抽出する

私はseaborn clustermapを使用してクラスターを作成していますが、視覚的にはうまく機能します(これは example で非常によく似た結果になります)。

ただし、クラスターをプログラムで抽出する方法を理解するのに苦労しています。たとえば、リンクの例では、1-1 rh、1-1 lh、5-1 rh、5-1 lhが適切なクラスターを形成していることをどのように確認できますか?視覚的には簡単です。データと樹状図を調べる方法を使用しようとしていますが、ほとんど成功していません

[〜#〜] edit [〜#〜]例のコード:

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)

どのモデルがどのクラスターにあるかをresultからプルするにはどうすればよいですか?

EDIT2resultlinkagedendrogram_colと一緒に持ち込みます。 fcluster を使用します。しかし、それを選択するためのしきい値は私を混乱させます。しきい値より高いヒートマップの値が一緒にクラスター化されると思いますか?

23
sedavidw

result.linkage.dendrogram_colまたはresult.linkage.dendrogram_rowの使用は現在は機能しますが、実装の詳細のようです。最も安全な方法は、最初にリンケージを明示的に計算し、それらをclustermap関数に渡すことです。この関数には、そのためのrow_linkageおよびcol_linkageパラメータがあります。

例の最後の行(result = ...)を次のコードに置き換えると、以前と同じ結果が得られますが、row_linkageおよびcol_linkage変数も使用できますfclusterなど.

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)

この特定の例では、correlations配列が対称的であり、したがってrow_linkagecol_linkageが同一になるため、コードをさらに簡略化できます。

注:以前の回答には、seabornのコードの動作に応じたdistance.squareshapeへの呼び出しが含まれていましたが、- バグです

15
Marcel M

おそらく、クラスターメンバーシップを使用して、データフレームに新しい列が必要です。私はこれをウェブ全体から盗まれたコードの組み立てられたスニペットから何とかしてやった:

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

したがって、これにより、緑色または赤色のラベルが付けられたクラスターの「g」または「r」を含む列が得られます。デンドログラムをプロットし、y軸の値に注目して、color_thresholdを決定します。

6
sjc