クラスター化ヒートマップ

米国各州の社会指標の z スコアのヒートマップ。行と列のデンドログラム、国勢調査地域のカラーバー付き。

クラスター化ヒートマップ

各行が観測、各列が変数で、各セルはその z スコアです(変数の平均より下は青、上は赤)。行と列は階層的クラスタリング(ユークリッド距離に対するウォード法)で並べ替えられ、デンドログラムが併合の履歴を示します。左のカラーバーは各行の既知のグループを表すので、教師なしの樹形図がそれを再発見しているか、そしてどの変数が分割を左右しているかが一目でわかります。

データは statsmodels の statecrime データセット(2009 年の数値)に含まれる米国 50 州とコロンビア特別区です。人口 10 万人あたりの暴力犯罪率と殺人率、高校卒業者の割合、貧困層の割合、ひとり親世帯の割合、白人の割合、都市人口の割合を用います。カラーバーは国勢調査局の地域区分です。クラスタリングと描画は seaborn.clustermap が行い、scipy.cluster.hierarchy で行の樹形図を 4 つのクラスターに切って、4 地域との調整ランド指数を計算します。どの州どうしが似ているかを、地理は部分的にしか説明しません。

コードおよび図中のテキストは英語です。

clustered-heatmap.py · 56 行
ダウンロード GitHub
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from matplotlib.patches import Patch
from scipy.cluster.hierarchy import fcluster
import statsmodels.api as sm
from sklearn.metrics import adjusted_rand_score

# Data: 7 social indicators of 51 US states (incl. DC), z-scored per column;
# US Census region as row annotation
df = sm.datasets.statecrime.load_pandas().data
df.index = df.index.str.strip()
Z = (df - df.mean()) / df.std()
Z.columns = ["Violent crime", "Murder", "High-school grad.", "Poverty", "Single parent",
             "White", "Urban"]
regions = {"Northeast": ["Connecticut", "Maine", "Massachusetts", "New Hampshire", "New Jersey",
                         "New York", "Pennsylvania", "Rhode Island", "Vermont"],
           "Midwest": ["Illinois", "Indiana", "Iowa", "Kansas", "Michigan", "Minnesota", "Missouri",
                       "Nebraska", "North Dakota", "Ohio", "South Dakota", "Wisconsin"],
           "West": ["Alaska", "Arizona", "California", "Colorado", "Hawaii", "Idaho", "Montana",
                    "Nevada", "New Mexico", "Oregon", "Utah", "Washington", "Wyoming"]}
region = pd.Series([next((r for r, s in regions.items() if st in s), "South") for st in Z.index],
                   index=Z.index, name="Region")
palette = dict(zip(["Northeast", "Midwest", "South", "West"],
                   ["#007AFF", "#FF9500", "#FF3B30", "#34C759"]))

with plt.rc_context({"figure.constrained_layout.use": False}):
    g = sns.clustermap(Z, method="ward", metric="euclidean", cmap="RdBu_r", center=0,
                       vmin=-3, vmax=3, row_colors=region.map(palette), yticklabels=True,
                       figsize=(8.5, 10), dendrogram_ratio=(0.14, 0.12), colors_ratio=0.025,
                       cbar_pos=(0.02, 0.83, 0.025, 0.11),
                       cbar_kws=dict(label="z-score", ticks=[-3, 0, 3]),
                       tree_kws=dict(colors="#8E8E93", linewidths=0.8))

# How well does the row tree, cut into four clusters, recover the Census regions?
ari = adjusted_rand_score(region, fcluster(g.dendrogram_row.linkage, 4, "maxclust"))

g.ax_heatmap.set_xticklabels(g.ax_heatmap.get_xticklabels(), rotation=40, ha="right", fontsize=9.5)
g.ax_heatmap.set(xlabel="", ylabel="")
g.ax_heatmap.tick_params(axis="y", length=0, labelsize=7.5)
g.ax_heatmap.tick_params(axis="x", length=0)
g.ax_row_colors.set_xticklabels(["Region"], rotation=40, ha="right", fontsize=9.5)
g.ax_row_colors.tick_params(axis="x", length=0)
g.ax_cbar.tick_params(labelsize=8.5)
g.ax_cbar.yaxis.label.set_size(9)
g.ax_col_dendrogram.legend(handles=[Patch(color=c, label=n) for n, c in palette.items()],
                           loc="upper right", bbox_to_anchor=(1.0, 1.3), fontsize=9.5, ncol=2,
                           title="Census region", frameon=False, handlelength=1, handleheight=1)

g.figure.text(0.02, 1.04, "US states cluster by social profile more than by Census region",
              fontsize=13, fontweight="semibold", color="#1D1D1F")
g.figure.text(0.02, 1.01, f"Ward linkage on z-scores · n = {len(Z)} states (incl. DC) × {Z.shape[1]} "
              f"indicators · 4-cluster cut vs Census region: ARI = {ari:.2f}",
              fontsize=9.5, color="#6E6E73")
plt.show()

図にはオプションの PyStatlas スタイル を使用しています。同じ見た目にするには plt.style.use("pystatlas.mplstyle") を追加してください。

データの出典

  • US state crime and social indicators, 2009. U.S. Census Bureau. Statistical Abstract of the United States, state tables for 2009 (crime rates from the FBI Uniform Crime Reporting program). https://www.statsmodels.org/stable/datasets/generated/statecrime.html
    Compiled for statsmodels (sm.datasets.statecrime); public domain. See the statsmodels page for each variable's table and footnotes.

これらの例は統計手法を説明するためのものです。図のタイトルは、この特定のデータ(多くは小規模で、古く、部分的な標本)で図が示す内容を述べたものであり、実質的な問いに対する著者の立場ではありません。解釈、背景、データの質については、ここに挙げた元の出典を参照してください。

引用方法

PyStatlas は Thierry Warin が作成・運営しています。研究や業務に役立った場合は、ぜひ引用してください。

Warin, T. (2026). Clustered heatmap. In PyStatlas: A Python Gallery of Statistical Graphics for the Social Sciences. https://warint.github.io/pystatlas/multivariate/clustered-heatmap/

@misc{warin2026statlas,
  author       = {Warin, Thierry},
  title        = {PyStatlas: A Python Gallery of Statistical Graphics for the Social Sciences},
  year         = {2026},
  howpublished = {\url{https://warint.github.io/pystatlas/}},
  note         = {Source code: https://github.com/warint/pystatlas}
}

多変量解析とクラスタリングのその他のグラフ