デンドログラム(dendrogram、 樹形図)を確実に使いこなすための関連キーワードを難易度別に整理しました。
🍰 まずはやさしく
データの関係を木のように描いた図です。
グループの分かれ方を分かりやすくします。
部活のメンバーを似た者同士で分けます。
この図の読み方と使い方を学びましょう。
scipy.cluster.hierarchy.dendrogram(Z)デンドログラム(dendrogram, 樹形図)は、 階層クラスタリングの結果を樹形図の形で可視化したもの。 「どのサンプル同士が、 どの距離で結合するか」が一目で分かる、 階層クラスタリングの最終成果物です。
語源はギリシャ語 "dendron"(木)+ "gramma"(描いたもの)。 まさに「木の絵」。 生物学の系統樹(phylogenetic tree)も同じ概念で、 進化的近縁関係を樹形図で表します。
デンドログラムは3要素から成ります:
底から上に向かって、 「最初は各サンプルが独立」→「順次結合」→「最後に全部1つに」という過程を表現。
低い位置で結合する2サンプル = 似ている。 高い位置で結合 = 大きく異なる。
デンドログラムの真の威力は「後からクラスタ数を決められる」こと。 任意の高さで横に切ると、 そこから下のサブツリーが「k 個のクラスタ」になります:
切断高さの決め方:
scipy の dendrogram() 関数では、 color_threshold パラメータで「ここから上は色分けしない」と指定すると、 自然なクラスタが色で区別されます:
デフォルトは「最大距離の 70%」。 これにより視覚的にクラスタ構造が際立ちます。
SSDSE データを Ward 法でクラスタリングした典型的なデンドログラム解釈:
この階層構造から、 分析目的に応じた k を選べます。 細かく分析するなら k=8 で各地域圏に、 大きな区分なら k=2 で大都市 vs 地方に。
デンドログラムは、 単にクラスタを示すだけでなく、 多くの情報を提供します:
失敗1:横軸の順序を意味あるものと思う
デンドログラムの横軸(葉の順序)は、 アルゴリズムの実装や枝の入れ替えで変わります。 「左から3番目だから」「真ん中だから」に意味はない。 重要なのは結合の高さと階層構造のみ。
失敗2:「最も似ている」を誤読
「2サンプルが隣同士に描かれている = 似ている」は誤り。 隣でも結合高さが高ければ似ていない。 必ず結合高さで判断。
失敗3:切断高さの恣意性
「だいたいここで切ろう」は主観的。 客観的な指標と組み合わせて決定すべき。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | import pandas as pd # ── この抜粋だけで動くように、47 都道府県の特徴量を用意する ── # 英字の項目コードを使うので、2 行目の日本語名は読み飛ばす _d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) _d = _d[_d['SSDSE-B-2026'] == 2023] # 最新年度の 47 行 _cols = ['A1101', 'A1301', 'A1303', 'A4101', 'L3221'] # 総人口・15歳未満・65歳以上・出生数・消費支出 X = _d[_cols].astype(float).values names = _d['Prefecture'].tolist() # 樹形図の葉に出す都道府県名 from scipy.cluster.hierarchy import linkage, dendrogram from sklearn.preprocessing import StandardScaler import matplotlib.pyplot as plt # 標準化 X_std = StandardScaler().fit_transform(X) # 階層クラスタリング Z = linkage(X_std, method="ward") # デンドログラム描画 fig, ax = plt.subplots(figsize=(14, 6)) dendrogram(Z, labels=names, leaf_font_size=10, color_threshold=0.7*max(Z[:,2]), # 自然なクラスタ色分け ax=ax) ax.set_title("Ward 法によるデンドログラム", fontsize=14) ax.set_ylabel("結合距離") plt.tight_layout() plt.show() |
🍰 まずはやさしく
分析の結果として出てくる樹形図のことです。
データの階層構造を視覚的に捉えるために使います。
都道府県などのデータをグループ分けします。
図の縦軸と横軸が何を表すかを確認しましょう。
論文で階層クラスタリングの結果として登場する樹形図。 「デンドログラム」「樹形図」「ward 法のデンドログラムを示す」のような形で。 47都道府県のような中規模データの階層構造を可視化する最重要ツール。
デンドログラム とは:階層クラスタリングの結果を樹形図で表現したもの。縦軸は結合距離、横軸は個体。
🍰 まずはやさしく
似ているもの同士を線で結んだ絵です。
自然なグループの数を決めるために使います。
スマホのアプリをジャンル別に分けます。
図の形や色の意味について直感的に理解しましょう。

デンドログラムが意味を持つには、 結合距離が「ウルトラメトリック」(ultrametric)という強い条件を満たす必要があります:
$d(x, z) \le \max(d(x, y), d(y, z))$
これは通常の距離の3角不等式 $d(x,z) \le d(x,y) + d(y,z)$ より強い条件。 これがあるおかげで、 樹形図として一意に表現できます。
結合基準によってはウルトラメトリックが破れ(中央連結など)、 樹形図に「逆転」(枝が交差)が起きます。 Ward 法、 単連結、 完全連結、 群平均では発生しません。
デンドログラムには $2^{n-1}$ 通り の表示方法があります(各内部節点で左右の子を入れ替えられる)。 例えば 47県のデンドログラムは $2^{46} \approx 7 \times 10^{13}$ 通りの表示が可能。 でも階層構造(どこで結合するか)は同じ。
scipy では各実装が独自の順序で表示します。 多くの場合「リーフ間の距離を最小化する」順序(optimal leaf ordering)が使われ、 視覚的に分かりやすい配置になります。
デンドログラムから「2サンプル $x_i, x_j$ が結合した距離」を取り出した行列をcophenetic 距離行列と呼びます。
cophenetic correlation = (元の距離行列)vs(cophenetic 距離行列)の Pearson 相関。 これが大きい(0.7以上)と、 デンドログラムが元の距離構造を忠実に表現していることを意味します。 0.5以下なら、 階層クラスタリング自体が不適切な可能性。
生物学の系統樹(phylogenetic tree)もデンドログラムの一種。 種間の DNA 距離から進化的近縁関係を表現します。 ただし、 系統樹は「時間軸」(進化年代)を含むことが多く、 縦軸の意味が違います。
クラスタリングのデンドログラム:縦軸 = 不類似度
系統樹:縦軸 = 進化時間 or 遺伝距離
n が大きいと(n > 100)、 デンドログラムの葉が密集して読めなくなります。 対策:
seaborn の clustermap は、 行・列両方をクラスタリングしてヒートマップに重ねる強力なツール。
系統樹のような円形表示。 多数の葉でも見やすい。
生物分類でよく使われる、 デンドログラムに時系列情報を加えたもの。
デンドログラムは「階層クラスタリングの併合過程」を樹形図で示したもの。 縦軸は併合時の距離で、 切る高さによってクラスタ数が決まる。 SSDSE-B-2026 で 47 都道府県を A1101・A1303・L3221 の 3 変数でクラスタリングすると、 東京 1 県/首都圏 4-5 県/地方中核 8-10 県/その他 35 県のような階層構造が浮かぶ。
デンドログラム は「可視化」カテゴリの中核概念。 初めて触れる読者は、 まずこの「🎨 直感」セクションだけ通読し、 必要になった時点で「📐 数式」「🐍 Python」「⚠️ 落とし穴」へ戻る読み方が定着しやすいです。
散布図の点をドラッグすると、 右のデンドログラムがその場で組み直され、 切断高さスライダーを動かすとクラスタ数 k と点の色分けがリアルタイムに連動します。 「樹形図の高さ = 2 つのクラスタが併合された時の距離」であることを、 手を動かして体感してください(凝集型階層クラスタリング・ユークリッド距離)。
スライダーを下げる(低い高さで切る)ほど k は大きく(細かく)、 上げるほど k は小さく(粗く)なります。 低い位置で併合する点ほど「似ている」。 点を動かして 2 つの塊を離すと、 それらを最後に束ねる枝がぐんと高くなるのが見えるはずです。 この「高さの跳躍(ギャップ)」が自然な切断点の目印になります。 概念本体は 階層クラスタリング、 定番の結合基準は Ward 法 を参照。
🍰 まずはやさしく
図を作るための計算ルールをまとめたものです。
正確にグループを分けるために使います。
買い物の傾向が似ている人を計算で分けます。
図の根拠となる数式を詳しく見ていきましょう。
やさしい説明で掴んだ感覚を、ここで デンドログラム の定義式に対応づけます。下の式は左辺 $d_{Ward}(C_1, C_2)$ が何で決まるかを右辺で書き下したもので、x̄(平均)、分数(割り算) が現れます。それぞれの記号が何の量を指すのかは、次の「🔬 数式を言葉で読み解く」で 1 つずつ確かめてください。
上の数式を眺めるだけでは身につかないので、 各記号がどんな役割を担っているかを言葉で押さえます。 「数式を音読する習慣」がつくと、 論文や教科書を読むスピードが体感で 2 倍ほど上がります。
合成データではなく、 47 都道府県の家計支出(食料費、 教育費、 交通費、 通信費 4 変数)でデンドログラムを作成する手順を、 数値例で示します。
SSDSE-B-2026 から 4 変数を抽出します。 単位の異なる変数を扱うので、 標準化(z スコア化)が必須です。
1 2 3 4 5 6 7 8 9 10 11 | # 4 変数の平均と標準偏差(年間支出、 単位:千円、 仮想値) 食料費 :平均 850、 標準偏差 80 教育費 :平均 120、 標準偏差 35 交通費 :平均 290、 標準偏差 45 通信費 :平均 140、 標準偏差 18 # z スコア = (x - 平均) / 標準偏差 # 例:東京の食料費 1080 千円 → z = (1080-850)/80 ≈ +2.88 # 例:東京の教育費 220 千円 → z = (220-120)/35 ≈ +2.86 → 東京は 4 変数すべてで上位の特異値、 個別クラスタになる傾向 |
標準化後、 都道府県ペアごとのユークリッド距離 d(A, B) = √Σ(z_Aᵢ − z_Bᵢ)² を計算します。 47 都道府県なら 47×46/2 = 1081 ペア。
1 2 3 4 5 | # 距離例(標準化後) d(東京, 大阪) ≈ 2.4(大都市同士で近い) d(東京, 鳥取) ≈ 6.8(東京の特異性で遠い) d(青森, 秋田) ≈ 0.9(似た地方圏) d(大阪, 神奈川) ≈ 1.7 |
Ward 法ではクラスタを統合したときの分散増加量が最小のペアから結合します。 47 → 1 まで 46 ステップ。
# ステップ 1:青森・秋田 を統合 → 結合距離 ≈ 0.9
# ステップ 2:山形・福島 を統合 → 結合距離 ≈ 1.1
# ...
# ステップ 30:地方圏が大きな塊に → 結合距離 ≈ 4.5
# ステップ 40:都市圏グループ統合 → 結合距離 ≈ 7.2
# ステップ 45:東京が最後まで独立 → 結合距離 ≈ 11.0
# ステップ 46:東京を残りに統合 → 結合距離 ≈ 15.3
結合距離 5.5 のあたりで横線を引くと、 およそ 5 クラスタが得られます:
# cophenetic correlation(共経路相関)
# 元の距離行列とデンドログラムから読み取る距離(共経路距離)の Pearson 相関
# Ward 法:c ≈ 0.72
# 平均連結法:c ≈ 0.78
# 完全連結法:c ≈ 0.65
# 単連結法:c ≈ 0.55
→ 平均連結法が階層構造を最もよく保存しているが、
解釈のしやすさは Ward 法に分がある(球状クラスタを作る)
数式だけでは「実感」が湧きにくいので、 実データ data/raw/SSDSE-B-2026.csv(47 都道府県 × 12 年)で 1 度手計算してみると理解が定着します。
Ward 法で SSDSE-B-2026 (2023) の標準化済み A1101・A1303・L3221 をクラスタリングすると、 高さ 6.0 付近で 2 クラスタ(東京 vs 残り 46)、 高さ 3.5 で 4 クラスタ(東京/神奈川・大阪・愛知/首都圏/その他)に分かれる。 デンドログラムは併合距離が急増する箇所で切るのが定石。
| 都道府県 | A1101 総人口 | A1303 65 歳以上 | L3221 消費支出 |
|---|---|---|---|
| 東京都 | 14,086,000 | 3,205,000 | 341,320 |
| 神奈川県 | 9,229,000 | 2,390,000 | 306,565 |
| 大阪府 | 8,763,000 | 2,424,000 | 271,246 |
| 愛知県 | 7,477,000 | 1,923,000 | 300,221 |
| 埼玉県 | 7,331,000 | 2,012,000 | 344,092 |
| 千葉県 | 6,257,000 | 1,756,000 | 306,943 |
上記は SSDSE-B-2026 (2023) からの抜粋。 手計算で確認した値が、 後述の Python 実装で得る値と一致することを確認すると、 「数式とコードの対応関係」がクリアに見えるようになります。
SSDSE-B-2026 (2023年) から 4 県 (秋田・福井・京都・神奈川) を抽出し、 A1101 (総人口) [百万人] を 1 次元データとして単リンク法 (single linkage) で併合手順を手計算する。
1 2 3 4 5 | import numpy as np from scipy.cluster.hierarchy import linkage x = np.array([[0.9],[0.7],[2.5],[9.2]]) Z = linkage(x, method='single') print(f"連結履歴 (idx1, idx2, dist, n):\n{Z}") |
💬 手計算 (Step 2) の高さ 0.2, 1.6, 6.7 と Python の linkage 出力が完全一致。 SSDSE-B-2026 (2023) の A1101 を百万人単位 (小数第 1 位) にした 4 県データで、 秋田-福井 → +京都 → +神奈川 の順に併合される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from sklearn.cluster import KMeans, AgglomerativeClustering, DBSCAN from sklearn.preprocessing import StandardScaler from sklearn.metrics import silhouette_score import pandas as pd import numpy as np # データの標準化(重要!) scaler = StandardScaler() X_std = scaler.fit_transform(X) # k-means km = KMeans(n_clusters=3, random_state=0, n_init=10) labels_km = km.fit_predict(X_std) print(f'クラスタ中心: {km.cluster_centers_}') print(f'inertia: {km.inertia_}') # 階層クラスタリング(Ward法) agg = AgglomerativeClustering(n_clusters=3, linkage='ward') labels_agg = agg.fit_predict(X_std) # シルエットスコアで評価 score = silhouette_score(X_std, labels_km) print(f'シルエットスコア: {score:.3f}') |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import matplotlib.pyplot as plt inertias = [] silhouettes = [] for k in range(2, 11): km = KMeans(n_clusters=k, random_state=0, n_init=10).fit(X_std) inertias.append(km.inertia_) silhouettes.append(silhouette_score(X_std, km.labels_)) # エルボー法 plt.subplot(1, 2, 1) plt.plot(range(2, 11), inertias, 'o-') plt.xlabel('k'); plt.ylabel('inertia') # シルエット法 plt.subplot(1, 2, 2) plt.plot(range(2, 11), silhouettes, 'o-') plt.xlabel('k'); plt.ylabel('Silhouette') |
1 2 3 4 5 6 7 8 9 10 11 12 | import pandas as pd # labels はこのあとのブロックで作っているので、ここでも用意しておく _lab = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) labels = _lab[_lab['SSDSE-B-2026'] == 2023]['Prefecture'].values from scipy.cluster.hierarchy import linkage, dendrogram Z = linkage(X_std, method='ward') plt.figure(figsize=(14, 6)) dendrogram(Z, labels=labels, leaf_rotation=90) plt.show() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # 基本パターン import pandas as pd import numpy as np from scipy import stats import matplotlib.pyplot as plt import seaborn as sns # データ読み込み df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1) # 基本統計量 df.describe() # 可視化 sns.pairplot(df[['食料費(二人以上の世帯)', '教育費(二人以上の世帯)', '住居費(二人以上の世帯)']]) plt.show() |
このページの上にある3つの概念マップ(関係マップ、 包含マップ、 ツリーマップ)でこの概念の位置づけが視覚的に分かります。 関連手法を辿って学習を進めましょう。
統計データ活用コンペティションのSSDSE-B-2026データは、 47都道府県の社会経済データ。 この概念を使って以下のような分析ができます:
| 機能 | Python (pandas) | Python (scipy) |
|---|---|---|
| 要約統計 | df.describe() | stats.describe() |
| 平均 | df.mean() | np.mean() |
| 標準偏差 | df.std() | np.std() |
| 相関 | df.corr() | stats.pearsonr() |
| t検定 | — | stats.ttest_ind() |
| 回帰 | — | stats.linregress() |
| 分布フィッティング | — | stats.norm.fit() |
この概念は、 他の多くの統計概念と密接に関連しています。 ジャストインタイム型学習では、 必要に応じて関連用語へジャンプしながら全体像を構築します。
| グループ | 主要概念 |
|---|---|
| 記述統計 | 平均、 中央値、 最頻値、 分散、 標準偏差、 共分散、 相関係数 |
| 可視化 | ヒストグラム、 散布図、 箱ひげ図、 ヒートマップ |
| 推測統計 | 標本平均、 標準誤差、 信頼区間、 p値、 有意水準 |
| 確率分布 | 正規分布、 t分布、 χ²分布、 F分布、 二項分布 |
| 仮説検定 | t検定、 F検定、 χ²検定、 ノンパラ検定 |
| 回帰 | 単回帰、 重回帰、 OLS、 Ridge、 LASSO |
| 分類 | ロジスティック回帰、 決定木、 SVM、 k-NN |
| 教師なし学習 | クラスタリング、 PCA、 因子分析 |
| 時系列 | ARIMA、 VAR、 指数平滑法、 自己相関 |
| 因果推論 | DiD、 IV、 傾向スコア、 交絡変数 |
| 前処理 | 標準化、 正規化、 欠損値処理、 多重共線性対策 |
| 評価 | R²、 残差、 CV、 RMSE、 効果量 |
デンドログラムは「枝の高さ = 結合距離」「横の切断線 = クラスタ数の決定」が読みのポイントです。 横軸はサンプル (例: 都道府県名)、 縦軸は結合された時点での距離 (非類似度) を示します。 1 つのデンドログラムには「クラスタ階層構造」「サンプル間の関係性」「最適クラスタ数の手がかり」という 3 種類の情報が同時に格納されており、 読み解きの順序を体系化することが重要です。 特に、 結合の順序 (どのサンプルが先に結合するか) は、 連結法によって大きく変わるため、 同じデータでも複数の樹形図が描けることに留意が必要です。 下図は異なる連結法 (single/complete/average/ward) で同じデータからどう樹形図が変わるかを比較した例です。
図: single 連結はチェイン化、 complete はコンパクトな塊、 average/ward はバランス型。 同じデータでも結論が変わるので連結法選択は要注意。
| 連結法 | 距離定義 | クラスタ形状 | 外れ値感度 | 推奨用途 |
|---|---|---|---|---|
| 単連結 (single) | 最短距離 | 細長く繋がる | 高 (チェイン化) | 非凸クラスタ検出 |
| 完全連結 (complete) | 最長距離 | コンパクトな球状 | 中 (孤立で分離) | 同サイズ前提のクラスタ |
| 平均連結 (average/UPGMA) | 平均距離 | バランス型 | 低 | バイオ系系統樹 |
| Ward 法 | 分散最小化 | 同サイズの球状 | 低 | 汎用 (もっとも使われる) |
| 重心連結 (centroid) | 重心間距離 | 非単調性あり | 中 | 特定分野のみ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import pandas as pd import numpy as np from scipy.cluster.hierarchy import linkage, dendrogram, fcluster from scipy.spatial.distance import pdist from sklearn.preprocessing import StandardScaler import matplotlib.pyplot as plt df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1) df = df[df['年度'] == df['年度'].max()] # 最新年度の 47 行 # 「交通費」という列は無い(実際は「交通・通信費(二人以上の世帯)」) X = df[['食料費(二人以上の世帯)','教育費(二人以上の世帯)', '住居費(二人以上の世帯)','交通・通信費(二人以上の世帯)']].dropna() labels = df.loc[X.index, '都道府県'].values # 標準化 Xs = StandardScaler().fit_transform(X) # リンケージ計算(Ward 法) Z = linkage(Xs, method='ward', metric='euclidean') # デンドログラム描画 plt.figure(figsize=(15, 6)) dendrogram(Z, labels=labels, leaf_rotation=90, color_threshold=5.5) plt.axhline(y=5.5, color='red', linestyle='--', label='cut at 5.5') plt.legend() plt.tight_layout() plt.savefig('dendrogram_ward.png', dpi=150) # 任意の高さで切ってクラスタラベル取得 clusters = fcluster(Z, t=5.5, criterion='distance') result = pd.DataFrame({'都道府県': labels, 'cluster': clusters}) print(result.groupby('cluster')['都道府県'].apply(list)) |
1 2 3 4 5 6 7 8 9 10 11 | from sklearn.cluster import AgglomerativeClustering from sklearn.preprocessing import StandardScaler Xs = StandardScaler().fit_transform(X) # クラスタ数を指定 model = AgglomerativeClustering(n_clusters=5, linkage='ward') labels_pred = model.fit_predict(Xs) result = pd.DataFrame({'都道府県': labels, 'cluster': labels_pred}) print(result.groupby('cluster').size()) |
1 2 3 4 5 6 7 8 9 | from sklearn.cluster import AgglomerativeClustering model = AgglomerativeClustering( n_clusters=None, distance_threshold=5.5, linkage='ward' ) labels_pred = model.fit_predict(Xs) print(f'クラスタ数: {len(set(labels_pred))}') |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import seaborn as sns import pandas as pd from sklearn.preprocessing import StandardScaler Xs = pd.DataFrame( StandardScaler().fit_transform(X), index=labels, columns=X.columns ) g = sns.clustermap( Xs, method='ward', metric='euclidean', cmap='RdBu_r', center=0, figsize=(8, 12), dendrogram_ratio=(0.2, 0.1), ) g.savefig('clustermap.png', dpi=150) |
1 2 3 4 5 6 7 8 9 | from scipy.cluster.hierarchy import linkage, cophenet from scipy.spatial.distance import pdist d = pdist(Xs) for method in ['ward', 'average', 'complete', 'single']: Z = linkage(d, method=method) c, _ = cophenet(Z, d) print(f'{method:9s}: 共経路相関 = {c:.4f}') # → 値が高いほど階層構造を保存 |
1 2 3 4 5 6 7 | from sklearn.metrics import silhouette_score for k in range(2, 11): model = AgglomerativeClustering(n_clusters=k, linkage='ward') labs = model.fit_predict(Xs) score = silhouette_score(Xs, labs) print(f'k={k}: silhouette={score:.4f}') |
1 2 3 4 5 | from scipy.cluster.hierarchy import linkage, dendrogram Z = linkage(Xs, method='ward', optimal_ordering=True) # → 隣接する葉が距離的に近くなるように左右を入れ替え dendrogram(Z, labels=labels) |
公的統計(SSDSE-B-2026)を題材に、 最小限の Python コードで デンドログラム を動作させます。 まずはこのまま実行してみてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # デンドログラム を SSDSE-B-2026 で実行する最小コード import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023 年のみ抽出 print(df.shape) # (47, 112) print(df[['Prefecture','A1101','A1303','L3221']].head()) from scipy.cluster.hierarchy import linkage, dendrogram from sklearn.preprocessing import StandardScaler import matplotlib.pyplot as plt X = StandardScaler().fit_transform(df[['A1101','A1303','L3221']]) Z = linkage(X, method='ward') fig, ax = plt.subplots(figsize=(14,5)) dendrogram(Z, labels=df['Prefecture'].values, leaf_rotation=90, color_threshold=4.0, ax=ax) ax.set_title('SSDSE-B-2026: 47 都道府県 Ward 法') plt.tight_layout(); plt.savefig('dendrogram_demo.png', dpi=100) |
▶ 実行 を押せばこのページの中でそのまま動きます(ライブラリもデータも同梱済みで、 準備は要りません)。 手元の Python に移して動かすときは pip install matplotlib numpy pandas scikit-learn scipy seaborn が必要です。 読んでいるデータは data/raw/SSDSE-B-2026.csv。 日本語を含むので encoding='cp932' の指定を落とさないでください。
家計5項目で Ward 法を実行した結果。 「色分けされたクラスタ」は事前に指定した閾値で切ったもの。 距離が大きいところで切れば、 数の少ない大きなクラスタに分かれます。
| 前処理ステップ | 目的 | 欠如時の問題 |
|---|---|---|
| 変数の標準化 (z-score) | スケール差の除去 | 大きな単位の変数がクラスタを支配 |
| 外れ値処理 | 孤立点の影響回避 | single 連結だと長いチェイン形成 |
| 距離指標の選択 | データ特性に合った類似度 | カテゴリ変数にユークリッドだと無意味 |
| 連結法の選択 | クラスタ形状の制御 | single だと球状クラスタ検出不能 |
| サンプル数の事前確認 | O(n^2) メモリの確保 | n>10,000 でメモリ不足 |
| 誤解 | 正しい理解 |
|---|---|
| 「最適クラスタ数は枝が一番長く伸びる所」 | 経験則の 1 つに過ぎず、 シルエット係数や事前知識と併用すべき |
| 「並び順に意味がある」 | 並び替え自由度がある (回転可能)。 隣接 = 似ているとは限らない |
| 「Ward 法は常に最良」 | 同サイズ・球状クラスタ前提。 非凸データでは不適 |
| 「コフェネティック相関が高ければ OK」 | クラスタの解釈可能性は別問題。 業務的意味付けが必要 |
| 「全自動でクラスタ数決定可能」 | ドメイン知識による判断が不可欠 (k=3 か k=5 かは目的次第) |
StandardScaler で各変数を z-score 化 (単位差の影響を除去)scipy.spatial.distance.pdist でペアワイズ距離 (euclidean/correlation/cosine など)scipy.cluster.hierarchy.dendrogram で可視化| 可視化 | 前提手法 | 情報量 | 適用上限 |
|---|---|---|---|
| デンドログラム | 階層クラスタリング | クラスタ階層 + 距離 | n≈100 以下が可読 |
| エルボー図 | k-means | 最適 k の目安 | 大規模も可 |
| シルエット図 | 任意 | 各点の所属の確信度 | n≈1,000 まで実用的 |
| ヒートマップ + 樹形図 | 階層クラスタリング | クラスタ + 変数パターン | バイオ informatics で定番 |
| t-SNE/UMAP 散布図 | 次元削減 | 2D 位置関係 | 大規模可、 解釈注意 |
📤 読み方: デンドログラムはクラスタ構造の 階層性を示す唯一の可視化。 k-means など階層を持たない手法ではエルボー/シルエットで補完する。
47 都道府県を SSDSE-B-2026 の「総人口 (A1101)」「65 歳以上人口 (A1303)」「消費支出 (L3221)」の 3 変数 (標準化済み) でクラスタリングした結果、 デンドログラムは典型的に 4-5 クラスタ構成に切れます。 切断高さを変えると以下の解釈が得られます。
| 切断 k | クラスタ構成 | 業務的解釈 | 推奨用途 |
|---|---|---|---|
| 2 | 大都市圏 / 地方 | 「東京 + 大阪・神奈川 + 残り 44 県」の二極構造 | マクロ的な地域格差議論 |
| 3 | 超大都市 / 中規模都市圏 / 地方 | 東京 / 大阪・神奈川・愛知 / 残り 43 県 | 三層モデルでの政策設計 |
| 4 | 超大都市 / 大都市 / 地方中核 / 過疎 | 人口減少傾向の地域差を反映 | 地方創生施策のセグメンテーション |
| 5 | 上記 4 + 沖縄系 (特殊地域) | 沖縄が独立クラスタとして分離 | 特殊地域配慮の必要性議論 |
| 7 | 地域ブロック単位 | 北海道/東北/関東/中部/関西/中四国/九州沖縄に近い | 行政ブロック比較 |
このケースから、 「k は目的次第」「業務的解釈が伴ってこそ価値がある」というデンドログラム活用の本質が見えます。 数理的最適 k 候補と業務都合の交点を選ぶのがベストプラクティスです。 とりわけ公的データ分析では、 既存の行政分類 (都道府県 → ブロック → 地域圏) と統計的クラスタリングの結果を突き合わせ、 一致する箇所と異なる箇所の両方を議論する形が学術的・実務的に価値の高い分析になります。
color_threshold パラメータで切断高さを指定すると、 デンドログラム上でクラスタが自動着色される。 プレゼン資料に便利。truncate_mode='lastp' でクラスタ単位の表示が可能。デンドログラムは「1 枚で階層構造を全て見せる」唯一無二の可視化です。 適切な前処理 + 連結法選択 + 切断位置の業務解釈という 3 ステップを丁寧に踏むことで、 単なる「綺麗な樹形図」から「意思決定に使える分析結果」へと格上げできます。
下表は、 業界別にデンドログラムが用いられる代表的シナリオと特有の留意点をまとめたものです。 適用業界が違えば変数選択・連結法選択・切断位置決定の基準も大きく変わる点に注意してください。
| 業界 | 活用シナリオ | 推奨連結法 | 切断基準 |
|---|---|---|---|
| マーケティング | 顧客セグメンテーション (RFM 等) | Ward 法 | 業務に応じて 3-6 セグメント |
| バイオインフォマティクス | 遺伝子発現プロファイルの分類 | average (UPGMA) | 既知の機能的グループに合わせる |
| 金融 | 銘柄の相関構造分析 | complete (相関距離) | セクター分類との整合性 |
| 公衆衛生 | 疾病パターンの地域分類 | Ward 法 | 行政区域との整合性 |
| 教育 | 学習者の理解度クラスタリング | Ward 法 | 指導グループ数 (3-5) |
📤 ポイント: 業界によって「クラスタ数の妥当性」の判断基準が変わるのがデンドログラム活用の難所。 数学的最適性だけでなく、 業務的解釈可能性とのバランスで切断位置を決めるのが成功の鍵です。 加えて、 切断後はクラスタごとに代表的指標 (平均・割合・代表サンプル) を集計し、 「このクラスタはどう特徴付けられるのか」を 1-2 行で言語化する作業を必ず行います。 この言語化作業が、 単なる数値群を実務的な意思決定材料へと変換する最終ステップです。
単位の違う変数(万円、 %、 km² など)をそのまま使うと、 値の大きい変数が距離計算を支配し、 デンドログラムは事実上 1 変数だけで決まってしまいます。 例えば家計支出(千円単位、 数百〜数千)と人口密度(人/km²、 数百〜数千)を組み合わせると、 値域がそろっても分散が違えば結果は歪みます。 必ず StandardScaler または robust scaling で前処理してください。
同じデータでも Ward 法・単連結法・完全連結法・平均連結法で得られるクラスタは全く異なります。 単連結法は「鎖状クラスタ(chaining)」を作りやすく、 全部が 1 つの大クラスタになりがち。 完全連結法は球状を強要する。 Ward 法は分散を最小化するため一般的だが、 解釈は理論的根拠を踏まえて行う必要があります。 複数のリンケージ法を試して結果を比較するのが安全です。
デンドログラムをどの高さで切るか(カット位置)は、 多くの場合分析者の主観に委ねられます。 「縦の枝が長い場所で切る」という経験則はありますが、 数値的根拠としてはシルエット係数・ギャップ統計量・エルボー法などを併用するのが望ましい。 さらに、 ドメイン知識との整合性(5 クラスタが解釈しやすい etc.)も合わせて判断します。
階層クラスタリングは時間計算量 O(n²log n)〜O(n³)、 空間計算量 O(n²)。 n = 47 都道府県なら問題ありませんが、 n = 10000 以上では現実的に計算不能になります。 大規模データには k-means、 mini-batch k-means、 BIRCH、 HDBSCAN など他の手法を検討するか、 サブサンプリングで階層クラスタリングを近似する必要があります。
デンドログラムの葉(個体)の左右の並び順は本質的に任意です。 各内部ノードで左右の子は入れ替え可能なので、 同じ階層構造でも見た目はいくらでも変わります。 「視覚的に隣にあるから類似」と早合点しないでください。 真の距離は結合距離(縦方向の高さ)でしか分かりません。 順序を最適化する手法(optimal leaf ordering、 scipy の `optimal_ordering=True`)もあります。
外れ値(東京のような特異点)があると、 単連結法では「東京 → 大阪 → 神奈川 → ...」のような鎖状クラスタが生まれ、 階層構造が歪みます。 Ward 法でも結合距離の最後の数ステップが大きく跳ね上がり、 デンドログラムの上部が伸びすぎて他の構造が見えづらくなります。 外れ値を別途検出・除外、 もしくは対数変換などで前処理することを検討してください。
デンドログラムで頻出する失敗は、 (1) リンク法 (single/complete/average/Ward) の違いで樹形が大きく変わる、 (2) スケールが異なる変数を標準化せず投入し「金額」変数だけが効く、 (3) 高さ (距離) ではなく順序を見てしまい近さを誤読、 の 3 パターンです。 Ward 法 + 標準化を初期設定にして、 距離スケールを必ず読むのが基本です。
デンドログラム がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。
🌐 統計・データサイエンス › 教師なし学習 › クラスタリング › デンドログラム
中心に デンドログラム を置き、 そこから 階層クラスタリング・Ward法・結果可視化・k-means・PCA・因子分析 計 6 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語とあとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。
大きな円が小さな円を包含する Circle Packing 図。 「デンドログラム」は緑色でハイライト。
長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「デンドログラム」は緑色でハイライト。
| マップ | 分かること | こんな時に見る |
|---|---|---|
| 🔗 関係マップ | 手法間の横の関係(前提→発展→応用) | 「次に何を学べばよい?」 学習順序の判断 |
| ⭕ 包含マップ | 分類体系の入れ子構造(上位⊃下位) | 「この手法はどんなジャンルに属する?」 |
| 🌳 ツリーマップ | 分野の規模比較(面積=ボリューム) | 「データサイエンス全体の俯瞰像」 |
💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは デンドログラム の隣に何が並ぶかを、 包含マップとツリーマップは 統計・データサイエンス → クラスタリング → デンドログラム という入れ子の位置を示します。 「クラスタリングには他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。
「デンドログラム」は単独で完結する手法ではなく、 隣接領域と連携することで真価を発揮する。 具体的には次の 3 方向と密接につながる:
デンドログラムは階層クラスタリングの結果を木構造で可視化し、 切断高さで群数を決める。
「dendrogram」を含む手法選択は、 データの性質・分析目的・運用制約の 3 軸で決まる。 以下に典型シナリオと対応する手法の組合せを示す。
| シナリオ | 重視する観点 | 候補手法 |
|---|---|---|
| データが大規模 (n が多い、 高次元) | 計算コスト / メモリ / 並列化が必要 | 標準手法 等 |
| 外れ値が多い / ノイズあり | 頑健性 / 外れ値除去 / 中央値ベース | 高速版 等 |
| 解釈性を重視する | 線形 / 木構造 / ルールベース | 頑健版 等 |
| 予測精度を最優先する | アンサンブル / ハイパラ調整 / 交差検証 | 高次元対応版 等 |
| データが少ない | 正則化 / ベイズ / 転移学習 / 簡素なモデル | 小データ向け 等 |
| リアルタイム/オンライン処理 | ストリーミング / 軽量モデル / 逐次更新 | 解釈重視版 等 |
このセクションは追記の総まとめです。 上の各節(直感・数式・実値計算・落とし穴)を壊さずに、 「読み方の直感」「実務で必ず踏む落とし穴」「一歩進んだ発展トピック」を、 実データ data/raw/SSDSE-B-2026.csv(cp932・先頭の単位行 skip・2023 年 47 都道府県)から実測した数値とともに整理します。 変数は総人口 A1101・65 歳以上人口 A1303・消費支出 L3221 の 3 つを標準化して用いました。
7.22 → 12.41 と大きく跳ねます(後述の実測表)。 この「跳ぶ手前」で切るのが定石です。標準化した 3 変数を Ward 法で併合したときの、 最後の 8 回の併合距離(Z[:,2])の実測値です。 差分(ギャップ)が大きいところほど「離れた塊どうしを無理に束ねた」ことを意味します。
この「跳躍」を切断高さに対応させると、 実測で次のように分かれます(fcluster(Z, t=h, criterion='distance'))。
| 切断高さ h | クラスタ数 k | 実測の構成(代表) |
|---|---|---|
| 10.0 | 2 | 大都市系 9 県(北海道・埼玉・千葉・東京・神奈川ほか)/ 地方 38 県 |
| 5.0〜7.0 | 3 | 大都市系 9 / 地方を 24+14 に二分 |
| 4.0 | 4 | 東京都が単独クラスタとして分離(残り大都市 8/地方 24/地方 14) |
東京都は k=4 で単独クラスタになり、 かつ最後まで(高さ 12.41)他県と併合されません。 これは「東京が 3 変数すべてで突出した特異点」であることを、 デンドログラムが視覚的に示している例です。 これは既存の「🧮 SSDSE-B-2026 実値計算例」で述べた傾向と整合します。
デンドログラムが元の距離構造をどれだけ忠実に再現しているかはコーフェネティック相関(cophenetic correlation)で測れます(元の距離 vs 樹形図から読む共経路距離の Pearson 相関)。 同じ 3 変数・同じ距離行列に対して 4 つの連結法で実測しました。
| 連結法 | コーフェネティック相関(実測) | コメント |
|---|---|---|
| 群平均法(average/UPGMA) | 0.885 | 元距離を最もよく保存(今回の最良) |
| 単連結法(single) | 0.858 | 保存性は高いが鎖状に伸びやすい |
| Ward 法 | 0.750 | 解釈しやすい球状クラスタ。 都道府県分析の定番 |
| 完全連結法(complete) | 0.732 | コンパクトな塊を作るが保存性はやや低い |
重要な含意:忠実度(コーフェネティック相関)が最も高いのは群平均法ですが、 都道府県データでは分散増加を最小化して解釈しやすい塊を作る Ward 法が実務で選ばれます。 「数値的な忠実度」と「解釈のしやすさ」は別軸で、 どちらを重視するかは目的次第です。 なお、 本ページ既出の「⑤ 共経路相関係数の解釈」(Ward ≈ 0.72、 平均 ≈ 0.78 など)は概略値の説明で、 ここに示したのは同一設定での実測値です。 手元で再現するには次のコードを使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import pandas as pd from scipy.cluster.hierarchy import linkage, cophenet from scipy.spatial.distance import pdist from sklearn.preprocessing import StandardScaler df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) d = df[df['SSDSE-B-2026'] == 2023] Xs = StandardScaler().fit_transform(d[['A1101','A1303','L3221']]) D = pdist(Xs) for m in ['average','single','ward','complete']: Z = linkage(Xs if m == 'ward' else D, method=m) c, _ = cophenet(Z, D) print(f'{m:9s}: cophenetic corr = {c:.3f}') # average: 0.885 / single: 0.858 / ward: 0.750 / complete: 0.732 |
truncate_mode での要約、 ヒートマップとの併用(clustermap)、 インタラクティブ可視化、 あるいは k-means 法 や DBSCAN で粗く分けてから階層法を各塊に再適用、 などで対処します。fcluster で高さ(criterion='distance')または個数(criterion='maxclust')を指定して切ります。 実測では h=4.0 で東京が単独クラスタとして分離しました。optimal_ordering=True は木構造を変えずに、 隣接する葉が距離的に近くなるよう左右を入れ替え、 見やすさだけを改善します。 「並びに意味はない」原則は保たれます。seaborn.clustermap は行(県)と列(指標)の両方を階層クラスタリングしてヒートマップに重ね、 「どの県群でどの指標が高いか」を一望できます。 詳しくは ヒートマップ。scipy.cluster.hierarchy.inconsistent)。 値が大きい併合=「急に遠いものを束ねた」=自然な切れ目の候補で、 criterion='inconsistent' による自動切断に使えます。※ 上記の数値(併合距離・ギャップ・クラスタ構成・コーフェネティック相関)はすべて SSDSE-B-2026 (2023) の実測値です。 「🎮 触って理解する」ウィジェットの 7 点(A〜G)は操作体験のための架空データで、 実測値とは無関係です。