「階層クラスタリング」を理解するうえで必要なキーワードを 10 件以上提示します。 各チップから対応セクションへ移動できます。
30 秒結論 文脈 直感 数式 記号読み解き 実値計算 Python 実装 落とし穴 関連手法 関連用語 グループ教材 概念マップ
🍰 まずはやさしく
似たもの同士をまとめる家系図のような手法です。
データのグループ分けをするために使います。
部活のメンバーを性格で分けるときに便利です。
この章では仕組みと特徴について読みます。
scipy.cluster.hierarchy.linkage + dendrogram階層クラスタリング(hierarchical clustering)は、 サンプルを階層的(=入れ子状)にグループ化する手法。 結果はデンドログラム(樹形図)として可視化され、 「どのサンプル同士が、 どの段階で結合するか」が一目で分かります。
k-means との根本的違い:
これにより、 「2クラスタにしたらどう分かれる?3クラスタなら?4クラスタなら?」を一度の計算で全部見られるのが強み。
階層クラスタリングには、 結合方向の異なる2方式があります:
通常「階層クラスタリング」と言えば凝集型を指します。 以下も凝集型を中心に説明します。
「2つのクラスタの距離」をどう測るかで結果が変わります。 主要な選択肢:
| 結合法 | 距離の定義 | 特徴 |
|---|---|---|
| 単連結(single) | 最も近い2点の距離 | 細長いチェーン状クラスタ |
| 完全連結(complete) | 最も遠い2点の距離 | コンパクトな塊 |
| 群平均(average) | 全ペアの平均距離 | 単連結と完全連結の中間 |
| Ward 法 | 結合による分散増加量を最小化 | 均等サイズの球形クラスタ。 最も使われる |
| 中央連結 | 中心同士の距離 | 逆転が起きる場合あり |
選び方の指針:
4都道府県の (高齢化率, 死亡率) で、 単連結階層クラスタリングを追います:
| 県 | 高齢化率 | 死亡率 |
|---|---|---|
| A: 秋田 | 39 | 19 |
| B: 高知 | 36 | 17 |
| C: 東京 | 23 | 9 |
| D: 沖縄 | 23 | 11 |
初期距離行列(ユークリッド距離):
ステップ1:C と D(距離2.00)を結合 → クラスタ {C,D} 誕生。 結合高さ=2.00
ステップ2:残り {A}, {B}, {C,D} で再計算。 単連結なら d({A},{C,D}) = min(d(A,C), d(A,D)) = 17.89、 d({B},{C,D}) = min(14.32, 15.26) = 14.32、 d(A,B) = 3.61 ← 最短。 → A と B を結合 → クラスタ {A,B} 誕生。 結合高さ=3.61
ステップ3:残り {A,B}, {C,D}。 単連結なら距離 = min(全ペア) = min(18.87, 17.89, 15.26, 14.32) = 14.32。 → 2クラスタを最終結合。 結合高さ=14.32
結果のデンドログラム:
高さ 14.32 ─┐ │ ┌────────────────┐高さ 3.61 ──┤ │ ┌───┐ │ │ │ │ │ │高さ 2.00 ──┤ │ │ ┌─┴─┐ │ A B A B C D
2クラスタに切る場合:{A,B} と {C,D}(=「高齢化進行群」と「若年群」)。 4クラスタなら個別の4県。
階層クラスタリングの強みは「k を後で決められる」。 デンドログラムを見て:
| 長所 | 短所 |
|---|---|
| k を後で決められる | 計算量 O(n³)(大規模困難) |
| 階層構造が見える(デンドログラム) | 一度結合したら変更不可能 |
| 結合基準の選択肢が豊富 | 結合基準で結果が大きく変わる |
| 球形でないクラスタも捕捉可(単連結) | 外れ値に弱い(単連結) |
| 解釈しやすい樹形図 | 逆転(inversion)が起きる場合あり |
🎯 このコードでやること:階層的クラスタリング — 樹形図で群構造を表現に関連するステップ #1。最初のスニペットです。SSDSE-B-2026 を読み込みます。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 47都道府県の距離行列(ユークリッド)から樹形図を構築
# 標準化済み X (shape=(47, 4)):
# pref z_age z_inc z_pop z_unemp
# 0 北海道 0.31 -0.42 0.85 0.62
# 1 青森県 1.45 -1.21 -0.62 0.93
# 2 岩手県 1.39 -0.72 -0.68 0.211 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 | 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 prefecture_names = _d['Prefecture'].tolist() # 樹形図の葉に出す都道府県名 from scipy.cluster.hierarchy import linkage, dendrogram, fcluster from sklearn.preprocessing import StandardScaler import matplotlib.pyplot as plt # 必ず標準化 X_std = StandardScaler().fit_transform(X) # Ward法で階層クラスタリング Z = linkage(X_std, method="ward") # デンドログラム描画 fig, ax = plt.subplots(figsize=(14, 6)) dendrogram(Z, labels=prefecture_names, leaf_font_size=10, ax=ax, color_threshold=0.7*max(Z[:,2])) # k=4 でクラスタ分割 labels = fcluster(Z, t=4, criterion="maxclust") print('クラスタ別の県数:', pd.Series(labels).value_counts().sort_index().to_dict()) |
📤 実行例(実測)
クラスタ別の県数: {1: 6, 2: 32, 3: 8, 4: 1}🍰 まずはやさしく
データを階層的に分ける分析の方法です。
似ているグループを視覚的に見つけるために使います。
都道府県をいくつかのタイプに分ける例があります。
この章では分析での使われ方を読みます。
論文で「階層クラスタリング」「デンドログラム」「Ward 法でクラスタリング」と書かれているとき。 「47都道府県を樹形図で類型化」のような用途で、 k-means と並ぶクラスタリングの2大手法の1つ。
階層クラスタリング とは:サンプルを1点ずつ結合(または分割)してデンドログラム(樹形図)を作り、任意の階層で切ってクラスタを得る。
このセクションは「階層クラスタリング」を扱う 用語ページ です。 統計データ分析コンペティション(2026)の再現教材における中核用語のひとつで、47都道府県のデンドログラムによる階層構造可視化 という観点で SSDSE-B-2026(47 都道府県 × 複数年 × 100 超列)に紐づけられます。
位置づけ:相関・線形回帰・仮説検定 といった基礎用語群と並列であり、応用としては 内生性・IV・DID・クラスタリング 等へ繋がります。
🍰 まずはやさしく
似ている順に結んでいくパズルのようなものです。
グループの分かれ方を直感的に知るために使います。
スマホのアプリをジャンル別に分けるイメージです。
この章ではグループの作り方を読みます。

2クラスタ $A, B$ の距離 $d(A, B) = \min_{a \in A, b \in B} d(a, b)$。 最近隣の距離が0に近いペアを次々結合するので、 細長い「鎖状」クラスタができやすい。 「友達の友達は友達」的なつながりを捕捉。 ただし外れ値1つが「橋」になって、 別のクラスタを巻き込むことも(chaining問題)。
$d(A, B) = \max_{a \in A, b \in B} d(a, b)$。 最遠の距離を見るので、 結合された後のクラスタがコンパクトになる。 ただし外れ値があると最遠が大きくなり、 結合を遅らせる。
「2クラスタを結合したときの分散増加量」が最小のペアを選ぶ:
$\Delta(A, B) = \sum_{x \in A \cup B} \|x - \mu_{AB}\|^2 - \sum_{x \in A} \|x - \mu_A\|^2 - \sum_{x \in B} \|x - \mu_B\|^2$
これをLance-Williams 更新式で効率的に計算できる:
$d_{Ward}(A \cup B, C) = \frac{n_A + n_C}{n_A + n_B + n_C} d(A,C) + \frac{n_B + n_C}{n_A + n_B + n_C} d(B,C) - \frac{n_C}{n_A + n_B + n_C} d(A,B)$
結果として、 均等サイズの球形クラスタが形成されやすい性質を持ちます。 k-means と似た性質(ユークリッド距離前提、 球形向き)ですが、 階層構造が見えるのが利点。
基本実装は $O(n^3)$。 例えば n=1000 で 10億回の計算。 大規模データには厳しい。
効率化:(i) 近接行列を最初に計算し再利用、 (ii) SLINK アルゴリズム(単連結用 O(n²))、 (iii) BIRCH との組み合わせで近似。 n < 5000 程度なら普通に scipy で実行可能。
中央連結や重心連結では、 「結合距離が前の結合より小さくなる」逆転が起きることがある。 デンドログラムを描いたときに枝が交差し、 解釈不能に。 Ward 法や単連結・完全連結・群平均ではこれは発生しません。 だから実用では Ward 法が選ばれることが多い。
階層クラスタリング を一言でいえば「47都道府県のデンドログラムによる階層構造可視化」。 47 都道府県という小さな母集団でも、 SSDSE-B-2026 の A1101 列に注目すると、 大都市圏と地方の差・人口規模に伴う相対比較など、 様々なパターンが見えてきます。
比喩でいうと、 階層クラスタリング はデータ分析の「眼鏡」のようなもの。 同じデータでも眼鏡を変えれば、 平均(中心)・分散(ばらつき)・相関(連動)・因果(影響)と、 異なる情報が浮かび上がります。 SSDSE-B-2026 を題材に、 この眼鏡をかけてみるのが本ページの狙いです。
階層クラスタリングは 「点をボトムアップに併合し、 結果を樹形図 (dendrogram) で表現する」。 以下 3 つの図で「凝集の過程」「連結法の違い」「樹形図切断と k 決定」を視覚化する。
→ 各ステップで最近接ペアを併合。 N-1 回の併合で 1 クラスタに集約され、 過程全体が樹形図に記録される。
→ single は鎖状、 complete は球状、 average は中庸、 Ward は分散最小化。 実務では Ward 法が最も安定で多用される。
→ 樹形図を水平線で切断するとクラスタ数 k が決まる。 高さは併合時の距離 (非類似度)。 ジャンプの大きい高さで切ると自然なクラスタが得られる。
→ SSDSE-B-2026 から作成した 47 都道府県の階層クラスタリング結果。 縦軸はクラスタ統合時の Ward 距離。 高さ閾値を 4 群相当に切ると、 「東京・大阪 / 首都圏隣県 / 中規模都市県 / 地方県」のような構造が浮かび上がる。
scipy.cluster.hierarchy.linkage で Ward 階層化するときの引数を答えよ。| 観点 | 階層クラスタリング | k-means |
|---|---|---|
| k の事前指定 | 不要(デンドログラムから後決め) | 必要 |
| 計算量 | $O(n^2 \log n)$ — 大規模に不利 | $O(nkI)$ — スケール容易 |
| 出力形式 | デンドログラム + 階層構造 | k 個のフラットなクラスタ |
| 再現性 | 完全に決定論的 | 初期値依存(要 random_state) |
| 適例 | 分類体系の発見、 系統樹 | 大規模データのセグメント化 |
→ 小〜中規模 (n < 1000) で構造を見たいときは階層、 大規模で k が事前に決まるなら k-means。 両者を組み合わせる「2 段階クラスタリング」も有効。
🍰 まずはやさしく
グループ同士の距離を計算するルールです。
正しくグループを分ける基準を決めるために使います。
買い物の傾向が似ている人をまとめる計算に似ています。
この章では具体的な数式について読みます。
階層クラスタリング の代表的な定義式は次のとおりです。
$$ d(C_i \cup C_j, C_k) = \alpha_i d(C_i, C_k) + \alpha_j d(C_j, C_k) + \beta d(C_i, C_j) + \gamma \lvert d(C_i,C_k) - d(C_j,C_k)\rvert $$ここで使われる記号や演算の意味は次節で言葉に翻訳します。
数式の各記号を、日本語の意味に変換します。
階層クラスタリングを使いこなすカギは、 「結合基準 (linkage)」 と「距離尺度」、 そして デンドログラムをどこで切るかの 3 点にあります。 ここでは SSDSE-B-2026 を題材に、 これらの選択が結果に与える影響を実証的に示します。
|
Ward 法は球状で同程度の大きさのクラスタを作りやすい一方、 Single 法は「鎖状」につながる傾向(chaining 問題)があり、 SSDSE-B-2026 のような少数都道府県データでは 1 つの大クラスタ + 数個の単独都道府県になりがちです。
| 距離 | 特徴 | 向く場面 |
|---|---|---|
| Euclidean | L2 ノルム | 標準化済み量的データ |
| Manhattan | L1 ノルム | 外れ値耐性 |
| Correlation | パターン類似 | 時系列の形状比較 |
| Cosine | 方向の類似 | 高次元疎データ |
SSDSE-B-2026 で都道府県を意味のあるクラスタにまとめるには、 「距離閾値 t」を 視覚的と 統計的の両方で決める必要があります。 視覚的には、 デンドログラムで「大きな谷」が見えるところを切断します。 統計的には、 シルエット係数や inconsistency 係数をプロットして、 ピークを探すのが定石です。
|
上のコードを SSDSE-B-2026 で実行すると、 多くの場合 k=3 or k=4 で silhouette が最大になります。 そこを切断点として採用し、 デンドログラム上に水平線を引いて報告書に貼り付けるのが定番です。 ただし、 silhouette だけに頼らず、 各クラスタの構成都道府県を地理的・経済的に解釈できるか必ず確認してください。
階層クラスタリングは「クラスタ間の距離関係を 木構造として可視化できる」点が最大の魅力です。 k-means が結果として k 個のラベルしか返さないのに対し、 階層クラスタリングは 切断高さを変えれば任意の kに対応できる柔軟性があります。 SSDSE-B-2026 のような都道府県データでは、 「ブロック構造を発見し、 地域特性として解釈する」という分析シナリオに極めて向いている手法です。
本ページでは「階層クラスタリング」を 12 セクション(🔖 キーワード索引/💡 30 秒結論/📍 文脈/🎨 直感/📐 数式/🔬 数式を言葉で読み解く/🧮 実値計算/🐍 Python 実装/⚠️ 落とし穴/🌐 関連手法/🔗 関連用語/📚 グループ教材)で完結に整理しました。 SSDSE-B-2026 を素材に、 概念の輪郭・式の意味・実装手順・典型的な失敗パターンの 4 点を最低限押さえれば、 統計データ分析コンペの現場で迷わず使えるはずです。
SSDSE-B-2026 の数値列を標準化し、 Ward 法でクラスタリングします。 結合距離の典型的構造を把握しましょう。
| k | 構造的特徴 | シルエット | 解釈例 |
|---|---|---|---|
| 2 | 大首都圏 vs 地方 | 高 | 最も粗い構造 |
| 3 | 首都圏/地方都市/過疎地 | 最高 | 解釈バランス◎ |
| 4 | + 観光地特化 | 中 | 沖縄・北海道が独立 |
| 8 | 細分化 | 低下 | 過細 |
🎯 このコードでやること:階層的クラスタリング — 樹形図で群構造を表現に関連するステップ #5。仮説検定・モデル評価を行います。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 47都道府県の距離行列(ユークリッド)から樹形図を構築
# 標準化済み X (shape=(47, 4)):
# pref z_age z_inc z_pop z_unemp
# 0 北海道 0.31 -0.42 0.85 0.62
# 1 青森県 1.45 -1.21 -0.62 0.93
# 2 岩手県 1.39 -0.72 -0.68 0.211 2 3 4 5 6 7 8 9 10 11 12 13 | import pandas as pd from scipy.cluster.hierarchy import linkage, fcluster, dendrogram from sklearn.preprocessing import StandardScaler from sklearn.metrics import silhouette_score df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) num = df[df['SSDSE-B-2026'] == 2023].select_dtypes(include='number').dropna() X = StandardScaler().fit_transform(num) Z = linkage(X, method='ward') for k in [2, 3, 4, 5, 8]: labels = fcluster(Z, t=k, criterion='maxclust') print(f'k={k}: silhouette = {silhouette_score(X, labels):.3f}') |
📤 実行例(実測) k=2: silhouette = 0.595 k=3: silhouette = 0.569 k=4: silhouette = 0.193 k=5: silhouette = 0.172 k=8: silhouette = 0.154
SSDSE-B-2026(公的統計の社会・教育系データセット、 47 都道府県 × 10 年分超 × 100 以上の列)を用いて、 「階層クラスタリング」を体感します。 ファイル名は SSDSE-B-2026.csv、 読み込みは下記の Python コードで行います。
1 2 3 4 5 6 7 8 | import pandas as pd # SSDSE-B-2026 を読み込む(cp932 / Shift_JIS) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932') print(df.shape) # (564, 112) print(df['SSDSE-B-2026'].unique()) # 含まれる年度 latest = df[df['SSDSE-B-2026'] == df['SSDSE-B-2026'].max()].copy() print(latest[['Prefecture', 'A1101', 'A4101']].head()) |
ここで使った中心列 A1101 は SSDSE-B-2026 における 47都道府県のデンドログラムによる階層構造可視化 に関連する指標です。 算出例:
A1101 平均と標準偏差を求めるA1101 と A4101 の相関(線形・順位)を比較する合成 1D 点 [1, 3, 6, 10] でウォード法の併合手順を手計算する。
1 2 3 4 5 | import numpy as np from scipy.cluster.hierarchy import linkage x = np.array([[1],[3],[6],[10]]) Z = linkage(x, method='ward') print(Z) |
💬 手計算 (Step 3) と Python 出力が一致 (ward は分散ベースで距離計算)。
🎯 このコードでやること:階層的クラスタリング — 樹形図で群構造を表現に関連するステップ #2。基本統計量を計算します。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 47都道府県の距離行列(ユークリッド)から樹形図を構築
# 標準化済み X (shape=(47, 4)):
# pref z_age z_inc z_pop z_unemp
# 0 北海道 0.31 -0.42 0.85 0.62
# 1 青森県 1.45 -1.21 -0.62 0.93
# 2 岩手県 1.39 -0.72 -0.68 0.211 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}') |
📤 実行例(実測) クラスタ中心: [[ 0.00000000e+00 -4.26887378e-01 -4.24827214e-01 -4.28664223e-01 -4.28816473e-01 -4.26767938e-01 -4.30565549e-01 -4.31579131e-01 -4.31568592e-01 -4.31476064e-01 -4.18132818e-01 -4.16503746e-01 -4.19602865e-01 -4.41442183e-01 -4.40015436e-01 -4.42172372e-01 -4.24107040e-01 -4.24561197e-01 -4.23614684e-01 2.28609785e-01 -4.38974102e-01 -4.38992799e-01 -4.38175840e-01 -3.72161037e
🎯 このコードでやること:階層的クラスタリング — 樹形図で群構造を表現に関連するステップ #3。可視化(散布図/樹形図/時系列プロット)を描きます。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 47都道府県の距離行列(ユークリッド)から樹形図を構築
# 標準化済み X (shape=(47, 4)):
# pref z_age z_inc z_pop z_unemp
# 0 北海道 0.31 -0.42 0.85 0.62
# 1 青森県 1.45 -1.21 -0.62 0.93
# 2 岩手県 1.39 -0.72 -0.68 0.211 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') |
📤 このブロックは標準出力には何も出さない
🎯 このコードでやること:階層的クラスタリング — 樹形図で群構造を表現に関連するステップ #4。主要な指標(係数・統計量・スコア)を算出します。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 47都道府県の距離行列(ユークリッド)から樹形図を構築
# 標準化済み X (shape=(47, 4)):
# pref z_age z_inc z_pop z_unemp
# 0 北海道 0.31 -0.42 0.85 0.62
# 1 青森県 1.45 -1.21 -0.62 0.93
# 2 岩手県 1.39 -0.72 -0.68 0.211 2 3 4 5 6 | 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() |
📤 このブロックは標準出力には何も出さない
🎯 このコードでやること:階層的クラスタリング — 樹形図で群構造を表現に関連するステップ #6。結果を整形して表示します。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 47都道府県の距離行列(ユークリッド)から樹形図を構築
# 標準化済み X (shape=(47, 4)):
# pref z_age z_inc z_pop z_unemp
# 0 北海道 0.31 -0.42 0.85 0.62
# 1 青森県 1.45 -1.21 -0.62 0.93
# 2 岩手県 1.39 -0.72 -0.68 0.211 2 3 4 5 6 7 8 9 10 11 12 13 14 | from scipy.cluster.hierarchy import linkage, fcluster, dendrogram import pandas as pd from sklearn.preprocessing import StandardScaler # 英字の項目コードと Prefecture を使うので、2 行目の日本語名を読み飛ばす df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) d23 = df[df['SSDSE-B-2026'] == 2023] # 全 47 県が残るよう、欠損のある列ごと落とす(行を落とすと県がいなくなる) num = d23.select_dtypes(include='number').dropna(axis=1) X = StandardScaler().fit_transform(num) Z = linkage(X, method='ward') labels = fcluster(Z, t=3, criterion='maxclust') dendrogram(Z, labels=d23['Prefecture'].values) print('クラスタ別県数:', pd.Series(labels).value_counts().to_dict()) |
📤 実行例(実測)
クラスタ別県数: {1: 38, 2: 8, 3: 1}🎯 このコードでやること:階層的クラスタリング — 樹形図で群構造を表現に関連するステップ #7。47都道府県データに当てはめて確認します。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 47都道府県の距離行列(ユークリッド)から樹形図を構築
# 標準化済み X (shape=(47, 4)):
# pref z_age z_inc z_pop z_unemp
# 0 北海道 0.31 -0.42 0.85 0.62
# 1 青森県 1.45 -1.21 -0.62 0.93
# 2 岩手県 1.39 -0.72 -0.68 0.211 2 3 4 5 6 | from sklearn.cluster import AgglomerativeClustering ac = AgglomerativeClustering(n_clusters=3, linkage='ward').fit(X) labels = ac.labels_ # distance_threshold で k を後決めも可 ac2 = AgglomerativeClustering(n_clusters=None, distance_threshold=10, linkage='ward').fit(X) |
📤 このブロックは標準出力には何も出さない
🎯 このコードでやること:階層的クラスタリング — 樹形図で群構造を表現に関連するステップ #8。比較・別パターンを検討します。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 47都道府県の距離行列(ユークリッド)から樹形図を構築
# 標準化済み X (shape=(47, 4)):
# pref z_age z_inc z_pop z_unemp
# 0 北海道 0.31 -0.42 0.85 0.62
# 1 青森県 1.45 -1.21 -0.62 0.93
# 2 岩手県 1.39 -0.72 -0.68 0.211 2 3 4 | import seaborn as sns # num は数値列だけの表。定数列があると標準化で 0 除算になり NaN が出るので落とす num_c = num.loc[:, num.std() > 0] sns.clustermap(num_c, standard_scale=1, method='ward', cmap='vlag') |
📤 このブロックは標準出力には何も出さない
🎯 このコードでやること:階層的クラスタリング — 樹形図で群構造を表現に関連するステップ #9。ハイパーパラメータを変えて再計算します。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 47都道府県の距離行列(ユークリッド)から樹形図を構築
# 標準化済み X (shape=(47, 4)):
# pref z_age z_inc z_pop z_unemp
# 0 北海道 0.31 -0.42 0.85 0.62
# 1 青森県 1.45 -1.21 -0.62 0.93
# 2 岩手県 1.39 -0.72 -0.68 0.211 2 3 | # pip install fastcluster import fastcluster Z = fastcluster.linkage(X, method='ward') # scipy の数倍高速 |
📤 このブロックは標準出力には何も出さない
| 用途 | 推奨 | 補足 |
|---|---|---|
| 小〜中規模 (n < 5000) | scipy.cluster.hierarchy | 業界標準 |
| パイプライン統合 | sklearn.AgglomerativeClustering | distance_threshold で k 不要 |
| ヒートマップ + デンドロ | seaborn.clustermap | 遺伝子発現解析の定番 |
| 高速版 | fastcluster | scipy 互換 API |
| 大規模(n > 10⁵) | BIRCH → 階層 | 2 段階アプローチ |
scipy / pandas / scikit-learn / statsmodels を中心とした標準的な実装例です。 まず CSV を読み込み、 次に 階層クラスタリング の解析を行います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import pandas as pd import numpy as np from scipy import stats df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932') df = df[df['SSDSE-B-2026'] == df['SSDSE-B-2026'].max()].copy() x = df['A1101'].astype(float).values y = df['A4101'].astype(float).values # 基本統計量 print('n =', len(x)) print('mean(x) =', np.mean(x)) print('std(x) =', np.std(x, ddof=1)) # 階層クラスタリング の代表的計算(用途に応じて scipy/statsmodels を切替える) r, p = stats.pearsonr(x, y) print(f'Pearson r = {r:.4f}, p = {p:.4g}') rs, ps = stats.spearmanr(x, y) print(f'Spearman rho = {rs:.4f}, p = {ps:.4g}') |
用途別の追加実装:
1 2 3 4 5 6 7 8 9 | # 標準化と簡易クラスタリングの例 from sklearn.preprocessing import StandardScaler from sklearn.cluster import KMeans X = df[['A1101', 'A4101']].astype(float).values Xs = StandardScaler().fit_transform(X) km = KMeans(n_clusters=4, n_init=10, random_state=0).fit(Xs) df['cluster'] = km.labels_ print(df[['Prefecture', 'A1101', 'A4101', 'cluster']].head(10)) |
1 2 3 4 5 6 7 | # 時系列(北海道の A1101)— 例として ARIMA 系の前処理 import statsmodels.api as sm ts = df.sort_values('SSDSE-B-2026').groupby('SSDSE-B-2026')['A1101'].mean() print(ts.tail()) res = sm.tsa.stattools.adfuller(ts) print('ADF stat:', res[0], 'p:', res[1]) |
linkage(metric='cityblock', method='ward') は警告も出さず動くので注意。 マンハッタン距離なら group_average や complete、 コサイン距離なら average を選ぶのが定石。 文書クラスタリングで「コサイン距離 + Ward」を見たら誤りです。階層クラスタリング を実務で扱う際に踏みやすい落とし穴を 5 件挙げます。
階層クラスタリング がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。
🌐 統計・データサイエンス › 教師なし学習 › クラスタリング › 階層クラスタリング
中心に 階層クラスタリング を置き、 そこから クラスタリング・k-means・標準化・Ward法・デンドログラム・PCA など 計 8 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語とあとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。
大きな円が小さな円を包含する Circle Packing 図。 「階層クラスタリング」は緑色でハイライト。
長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「階層クラスタリング」は緑色でハイライト。
| マップ | 分かること | こんな時に見る |
|---|---|---|
| 🔗 関係マップ | 手法間の横の関係(前提→発展→応用) | 「次に何を学べばよい?」 学習順序の判断 |
| ⭕ 包含マップ | 分類体系の入れ子構造(上位⊃下位) | 「この手法はどんなジャンルに属する?」 |
| 🌳 ツリーマップ | 分野の規模比較(面積=ボリューム) | 「データサイエンス全体の俯瞰像」 |
💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは 階層クラスタリング の隣に何が並ぶかを、 包含マップとツリーマップは 統計・データサイエンス → クラスタリング → 階層クラスタリング という入れ子の位置を示します。 「クラスタリングには他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。
「階層クラスタリング」は単独で完結する手法ではなく、 隣接領域と連携することで真価を発揮する。
上流の距離行列 (ユークリッド・マハラノビス・コサイン) を設計し、 並列の k-means・DBSCAN・GMM と階層性の有無を比較し、 下流のデンドログラム解釈・コフェネティック相関で評価する。 階層クラスタリングは「分割数を後から決められる」点で k-means と相補的で、 探索段階での全体像把握に向く。
SSDSE家計5項目で Ward 法を実行した結果。 似た都道府県が下から順にまとまっていく構造が一目で分かります。
階層クラスタリングでは「2つのクラスタ間の距離」をどう定義するかが核心:
| 連結法 | 距離の定義 | 特徴 |
|---|---|---|
| 単連結 (single) | 最も近いペアの距離 | 細長いクラスタ、 chain 効果 |
| 完全連結 (complete) | 最も遠いペアの距離 | コンパクトなクラスタ |
| 群平均 (average) | 全ペアの平均距離 | バランス型 |
| Ward法 | クラスタ内分散の増加最小 | 最も人気、 等サイズ |
| 重心 (centroid) | 重心同士の距離 | 逆転が起こる |
各点を独立クラスタとして開始 → 近いペアを順次マージ → 1つの大きなクラスタに。 一般的。
全データを1クラスタとして開始 → 順次分割 → 各点が独立クラスタに。 計算量大、 まれにしか使われない。
凝集型は O(n³) または O(n² log n)。 大規模データには不向き(k-means が O(n) で速い)。 n < 数千が現実的な目安。
ここまでのセクションを壊さず、 「直感」「落とし穴」「発展」を SSDSE-B-2026(cp932・2 行目メタ行を除外・2023 年の 47 都道府県)の実測値で補強します。 数値はすべて本ページ掲載の Python コードをそのまま流した実行結果で、 合成データを使う箇所は「架空」と明記します。
凝集型(agglomerative)の気持ちは驚くほど単純です。 いちばん近い 2 つのクラスタをくっつける、 これを 1 個になるまで繰り返すだけ。 くっつけた「高さ(=そのときの距離)」を縦に積み上げると、 それがそのまま デンドログラム(樹形図)になります。
「とりあえず ward」で済ませてはいけない理由を、 実データで見せます。 SSDSE-B-2026(2023 年・47 都道府県・数値 109 列を標準化)を、 4 つの連結法で同じく k=4 に切った結果が下表です(実測)。
| 連結法 | k=4 のクラスタ規模 | 最大融合距離 | コフェネティック相関 | Ward との一致度 (ARI) |
|---|---|---|---|---|
| Ward | 23 / 15 / 8 / 1 | 75.83 | 0.753 | —(基準) |
| 群平均 (average) | 38 / 7 / 1 / 1 | 44.16 | 0.949 | 0.41 |
| 完全連結 (complete) | 38 / 4 / 4 / 1 | 49.91 | 0.921 | 0.39 |
| 単連結 (single) | 44 / 1 / 1 / 1 | 25.53 | 0.929 | 0.11 |
読みどころは 3 つあります。
その他の実務上の罠(本ページ他セクションでも既述の要点を集約):スケール敏感で標準化必須(標準化を怠ると人口のような桁の大きい変数が距離を独占)、 計算量は O(n²〜n³)で大規模に弱い、 一度併合したら分け直せない貪欲(不可逆)、 外れ値 1 個が橋になって構造を壊す外れ値感度、 そして切断高さの任意性。 いずれも「複数設定で頑健性を確認する」姿勢で回避します。
関連ページ:Ward 法 / k-means / デンドログラム / クラスタリング / 距離(距離関数) / 標準化 / スペクトラルクラスタリング
左の散布図に点を置くと、 右に凝集型階層クラスタリングのデンドログラム(樹形図)が即座に描かれます。 連結法を切り替え、 切断高さのスライダーを動かすと、 散布図側のクラスタ着色がリアルタイムに連動します。 距離はユークリッド距離、 併合手順は Lance-Williams 更新式で正確に計算しています(外部ライブラリ不使用・完全オフライン)。
各点は最初「自分だけのクラスタ」。 毎ステップ、 いま最も近いクラスタ同士を1つに併合し、 その併合時の距離を樹形図の「高さ」として記録します。 これを点が1つのクラスタに集約されるまで繰り返すと、 全併合の履歴が樹形図になります。 樹形図を水平に切る高さを下げるほどクラスタ数 k は増え、 上げるほど減ります。 k を後から選べるのが階層クラスタリング最大の利点です。
linkage に渡します。切断高さの決め方には、 「高さのジャンプが大きい所で切る」「各 k でシルエット係数を比較する」「解釈したい地域数に合わせる」などがあります。 併合履歴と元距離の整合度はコフェネティック相関で評価できます。 大規模化では基本実装の O(n³) が壁になり、 単連結用の SLINK(O(n²))や近似法が使われます。
関連ページ:Ward 法 / k-means / デンドログラム / クラスタリング / 距離(距離関数) / DBSCAN
結合基準・距離尺度・評価指標・大規模化トピックを網羅。