「Ward 法」を理解するうえで必要なキーワードを 10 件以上提示します。 各チップから対応セクションへ移動できます。
30 秒結論 文脈 直感 数式 記号読み解き 実値計算 Python 実装 落とし穴 関連手法 関連用語 グループ教材 概念マップ
🍰 まずはやさしく
似たもの同士をまとめる方法です。
グループのばらつきを小さくするために使います。
部活のメンバーを似た性格で分けるときに便利です。
この章ではWard法の基本ルールを読みます。
scipy.cluster.hierarchy.linkage(X, method="ward")Ward 法(Ward's method)は、 階層クラスタリングにおける結合基準の1つで、 「2クラスタを結合したときのクラスタ内分散の増加量が最小になるペアを選ぶ」というルール。 結果として均等サイズの球形クラスタが形成されやすく、 多くの応用分野で第一選択肢として使われています。
核心アイデア:「結合してもまだまとまっているクラスタを優先する」。 つまり、 結合してもクラスタ内のばらつきがあまり増えないペアを選び続ける。 これにより内部凝集度が高いクラスタが順次形成されます。
2クラスタ $A$ と $B$ を結合するときの「分散増加量」$\Delta$:
$\Delta(A, B) = \sum_{x \in A \cup B} \|x - \mu_{A \cup B}\|^2 - \sum_{x \in A} \|x - \mu_A\|^2 - \sum_{x \in B} \|x - \mu_B\|^2$
ここで:
$\Delta$ は結合により増えるばらつき。 これが最小のペアを次々結合していきます。
毎回 $\Delta$ をゼロから計算すると O(n²) が反復で O(n³)。 代わりにLance-Williams 漸化式で効率化できます:
$d_{Ward}(A \cup B, C) = \frac{n_A + n_C}{n_T} d(A,C) + \frac{n_B + n_C}{n_T} d(B,C) - \frac{n_C}{n_T} d(A,B)$
$n_T = n_A + n_B + n_C$。 これにより新クラスタと他クラスタの距離を $O(1)$ で更新でき、 全体で $O(n^2)$ の効率(メモリは $O(n^2)$)。
linkage(X, method="ward") で一発SSDSE の「死亡率」「高齢化率」「保健医療費」「転入率」を Ward 法でクラスタリングすると、 典型的に次のような階層構造が出ます:
4クラスタで切れば実用的な「日本の地域類型」が得られ、 政策立案や市場調査に活用できます。
| 結合法 | 結果のクラスタ形状 | 外れ値の影響 | 適する場面 |
|---|---|---|---|
| 単連結 | 細長い鎖状 | 外れ値が「橋」になり破綻 | 細長いクラスタを期待 |
| 完全連結 | コンパクトな塊 | 外れ値で結合が遅れる | 明確に分離した群 |
| 群平均 | 中間的 | 中程度 | 汎用、 距離が任意 |
| Ward 法 | 均等サイズの球形 | 頑健 | 多くの応用での第一選択 |
| 中央連結 | 特殊な形 | 逆転発生あり | 特殊用途のみ |
🎯 このコードでやること:標準化した都道府県データに scipy.linkage(method="ward") を適用し、デンドログラムを描いて 4 クラスタに分割する。Ward 法の一連の流れを 1 つのスニペットで通す。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2)
# 47都道府県を高齢化率・所得・人口で Ward 法クラスタリング
# 入力 X(標準化済み, shape=(47, 3)):
# pref z_age z_inc z_pop
# 0 北海道 0.31 -0.42 0.85
# 1 青森県 1.45 -1.21 -0.62
# 2 岩手県 1.39 -0.72 -0.68
# 3 宮城県 -0.23 0.18 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 29 30 31 32 33 34 35 | # ── この抜粋で使うデータを用意します ── # 死亡率・高齢化率・保健医療費・転入率は SSDSE-B に直接の列が無いので、 # 実在する列から導出する。 from scipy.cluster.hierarchy import linkage, dendrogram, fcluster from sklearn.preprocessing import StandardScaler import matplotlib.pyplot as plt import pandas as pd _raw = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) _raw = _raw[_raw['SSDSE-B-2026'] == 2023] # 2023 年の 47 都道府県 df = pd.DataFrame({ 'Prefecture': _raw['Prefecture'].values, '死亡率': (_raw['A4200'] / _raw['A1101'] * 1000).values, # 人口千人あたり '高齢化率': (_raw['A1303'] / _raw['A1101'] * 100).values, # % '保健医療費': _raw['L322106'].astype(float).values, # 二人以上の世帯 '転入率': (_raw['A5101'] / _raw['A1101'] * 1000).values, # 人口千人あたり }) # データ準備 X = df[["死亡率", "高齢化率", "保健医療費", "転入率"]].values names = df["Prefecture"].values # 標準化(必須) X_std = StandardScaler().fit_transform(X) # Ward 法 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 法による47都道府県のクラスタリング") plt.tight_layout() plt.show() |
🍰 まずはやさしく
データを分けるための共通ルールです。
分析でグループ分けをするときに使います。
都道府県をいくつかのグループに分ける例があります。
この章では分析での使われ方を読みます。
論文で「Ward 法でクラスタリング」「Ward 法による階層クラスタリング」と書かれている部分。 階層クラスタリングの結合基準として最も使われる手法。 1963 年に Joe H. Ward Jr. が提唱。
Ward法 とは:階層クラスタリングの結合基準。クラスタ内の分散増加量が最小になるペアを結合していく。
このセクションは「Ward 法」を扱う 用語ページ です。 統計データ分析コンペティション(2026)の再現教材における中核用語のひとつで、47都道府県を Ward 法で 4 クラスタに分割 という観点で SSDSE-B-2026(47 都道府県 × 複数年 × 100 超列)に紐づけられます。
位置づけ:相関・線形回帰・仮説検定 といった基礎用語群と並列であり、応用としては 内生性・IV・DID・クラスタリング 等へ繋がります。
🍰 まずはやさしく
パズルのピースを合わせるような感覚です。
まとまりの良いグループを作るために使います。
スマホのアプリをジャンル別に分けるイメージです。
この章では仕組みのイメージを読みます。

Ward 法は実はk-means と密接に関連しています。 両者とも「クラスタ内分散の最小化」を目的としますが:
つまり Ward 法は「貪欲な k-means」とも言える。 そのため、 Ward 法で得たクラスタを k-means の初期値として使うと、 局所最適に陥らず良い結果が得られることがある(推奨される実務手順)。
$\Delta(A,B) = \frac{n_A n_B}{n_A + n_B} \|\mu_A - \mu_B\|^2$
この変形を見ると、 結合判定は「2クラスタ中心の距離 × サイズの調和平均」。 つまり:
結果として、 「小さく似ているクラスタ同士」が優先的に結合されます。 これが均等なクラスタを生む数学的根拠。
Joe H. Ward Jr. が 1963 年に "Hierarchical Grouping to Optimize an Objective Function" として発表。 元々は航空宇宙工学での分類問題に動機づけられた。 その後、 心理学、 生物学、 マーケティングなど幅広い分野で標準ツールに。
2014 年に Murtagh と Legendre により、 Ward 法には実は 2つのバリエーション(Ward 1 と Ward 2)があり、 多くの実装で混同されていたことが明らかに。 R の hclust(method="ward.D2") と method="ward.D" はこの違い。 通常は ward.D2(正式な Ward 法)を使うのが正しい。
| 項目 | Ward 法 | k-means |
|---|---|---|
| k の決定 | 後で(デンドログラムで) | 事前に |
| 階層構造 | 見える | 見えない |
| 計算量 | O(n²)〜O(n²log n) | O(n·k·d·iter) |
| 大規模データ | 不向き | 得意 |
| 確率モデル | なし | EM の特殊例 |
推奨ワークフロー:n < 1000 なら Ward 法で階層構造を確認 → 適切な k を決定 → 必要なら k-means で再計算。 n が大きければ最初から k-means。
Ward 法 を一言でいえば「47都道府県を Ward 法で 4 クラスタに分割」。 47 都道府県という小さな母集団でも、 SSDSE-B-2026 の A1101 列に注目すると、 大都市圏と地方の差・人口規模に伴う相対比較など、 様々なパターンが見えてきます。
比喩でいうと、 Ward 法 はデータ分析の「眼鏡」のようなもの。 同じデータでも眼鏡を変えれば、 平均(中心)・分散(ばらつき)・相関(連動)・因果(影響)と、 異なる情報が浮かび上がります。 SSDSE-B-2026 を題材に、 この眼鏡をかけてみるのが本ページの狙いです。
Ward 法は 「2 クラスタを合体させた時の群内平方和の増加量を最小化」 する階層的クラスタリング手法。 以下 3 図で「凝集の手順」「ESS の変化」「他連結法との比較」を可視化する。
→ 毎ステップで 「合体後の ESS 増加が最小」 なペアを選ぶ。 ESS = Σ‖xᵢ − 重心‖². 結果として均等サイズのクラスタが得られやすい。
→ K を増やすほど ESS は単調減少。 急激な減少が止まる「肘」 がクラスタ数の候補。 SSDSE-B-2026 都道府県では K=4 (関東/関西/地方都市/地方) が定番。
→ Ward は均等な球状クラスタ、 single は鎖状に伸びる、 complete は外れ値を単独クラスタにする。 都道府県分類は均等性が望ましいので Ward が第一選択。
→ SSDSE-B-2026 の 47 都道府県を Ward 法で階層クラスタリングした樹形図。 縦軸は群間距離(クラスタ統合時の SSE 増分)。 高さで切ると k 個のクラスタが得られる。
→ デンドログラムの一般形。 縦軸は併合時の距離、 横軸は各サンプル。 高さ閾値で水平に切ると最終的なクラスタが決まる。 Ward は階段が滑らかになりやすい。
scipy.cluster.hierarchy.fcluster の引数はどう書くか?fcluster(Z, t=4, criterion='maxclust') と書く。 t=4 がクラスタ数、 criterion='maxclust' が「最大クラスタ数で切断」の指定。| 連結法 | クラスタ間距離の定義 | 形状傾向 | 外れ値耐性 |
|---|---|---|---|
| 単連結 (single) | 最近点間距離 | 鎖状(伸びる) | 低 |
| 完全連結 (complete) | 最遠点間距離 | コンパクト | 中 |
| 群平均 (average) | 全ペア距離の平均 | 中庸 | 中 |
| Ward | SSE 増分の最小化 | 球状・等サイズ | 中〜高 |
→ Ward は k-means と同じ目的関数(SSE)を凝集型で最適化する。 都道府県分類のように均等な群を作りたいときに最適。
関連: 階層クラスタリング / k-means / デンドログラム / クラスタリング / 距離(距離関数)
3 点の 3 次元データを使い、「①Ward 距離(分散増加量)」「②Lance-Williams 更新式」「③最終的な総合判定(どのペアを結合するか)」の 3 式を Step 別に手計算し、Python で一致を確認する。
このコードでやること:p1=[1,2,3], p2=[4,5,6], p3=[7,8,9] の 3 点 3 次元データで Ward 法を手計算 → Python で再現 → 一致を確認する。
📥 入力データ:
$$ \Delta(A,B) = \frac{n_A n_B}{n_A + n_B}\,\|\bar{x}_A - \bar{x}_B\|^2 $$
$$ d(A_{12}, p3) = \frac{n_{A}+n_{p3}}{n_T}\,d(A,p3) + \frac{n_{B}+n_{p3}}{n_T}\,d(B,p3) - \frac{n_{p3}}{n_T}\,d(A,B) $$
ここで $n_T = n_{p1} + n_{p2} + n_{p3} = 1+1+1 = 3$。
このコードでやること:上記 3 ステップ(Ward 距離 → 総合判定 → Lance-Williams 更新)を scipy で再現し、リンク行列 Z の各行が手計算と一致することを確認する。
📥 入力データ:p1=[1,2,3], p2=[4,5,6], p3=[7,8,9] の配列
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 numpy as np from scipy.cluster.hierarchy import linkage # 3次元 3点データ X = np.array([[1,2,3], [4,5,6], [7,8,9]], dtype=float) # ① Ward 距離を手動確認 def ward_dist(a, b): na, nb = len(a), len(b) return (na*nb)/(na+nb) * np.sum((np.mean(a,axis=0) - np.mean(b,axis=0))**2) print("Δ(p1,p2) =", ward_dist(X[[0]], X[[1]])) # 13.5 print("Δ(p1,p3) =", ward_dist(X[[0]], X[[2]])) # 54.0 print("Δ(p2,p3) =", ward_dist(X[[1]], X[[2]])) # 13.5 # ② Lance-Williams で更新後の距離 d_A_p3 = 54.0 # Δ(p1,p3) d_B_p3 = 13.5 # Δ(p2,p3) d_AB = 13.5 # Δ(p1,p2) nT = 3 lw = (2/3)*d_A_p3 + (2/3)*d_B_p3 - (1/3)*d_AB print("Lance-Williams d(A12,p3) =", lw) # 40.5 # ③ scipy で確認: Z の各行 = [i, j, dist, n_merged] Z = linkage(X, method='ward') print("リンク行列 Z:") print(Z) |
📤 実行すると次の出力が得られる:
💬 scipy の ward 連結距離 Z[:,2] は分散増加量 Δ そのものではなく √(2Δ) のスケールで格納される。Z の 1 行目: p1(0) と p2(1) が距離 5.196 = √(2×13.5) で結合 → Step 2 の手計算 Δ=13.5 に対応。Z の 2 行目: 結合クラスタ A12(3) と p3(2) が距離 9.0 = √(2×40.5) で結合 → Step 6 の Lance-Williams 更新 Δ=40.5 に対応。手計算の Δ と scipy 出力が √(2Δ) の関係で整合。
🍰 まずはやさしく
計算でグループを決める数式です。
ばらつきが一番少ないペアを探すために使います。
買い物の傾向が似ている人を計算で分けるときに使えます。
この章では具体的な計算式について読みます。
Ward法は、 各ステップでクラスタ内分散の増加が最小になるペアをマージします:
$$ d(A, B) = \frac{n_A n_B}{n_A + n_B} \| \bar{x}_A - \bar{x}_B \|^2 $$
これによりサイズが似たクラスタが優先される傾向があります。 結果として「等サイズで凝集したクラスタ」が出来やすい。
Ward 法 の代表的な定義式は次のとおりです。
$$ \Delta E(A, B) = \frac{n_A n_B}{n_A + n_B}\, \lVert \bar{x}_A - \bar{x}_B \rVert^2 $$
ここで使われる記号や演算の意味は次節で言葉に翻訳します。
数式の各記号を、日本語の意味に変換します。
SSDSE-B-2026 に実在する「総人口(A1101)」「高齢化率(A1303÷A1101)」「消費支出(L3221)」「住宅地の標準価格(C5401)」の 4 変数で Ward 法を適用し、 4 つの「日本の地域類型」を抽出します。
🎯 このコードでやること:総人口・高齢化率・消費支出・住宅地標準価格の 4 変数を標準化して Ward 法を適用し、fcluster で 4 クラスタに切ってクラスタ別の平均値と、 デンドログラムの忠実度(コフェネティック相関)を出す。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2)
# 47都道府県を高齢化率・所得・人口で Ward 法クラスタリング
# 入力 X(標準化済み, shape=(47, 3)):
# pref z_age z_inc z_pop
# 0 北海道 0.31 -0.42 0.85
# 1 青森県 1.45 -1.21 -0.62
# 2 岩手県 1.39 -0.72 -0.68
# 3 宮城県 -0.23 0.18 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 29 | # ── この抜粋で使うデータを用意します(SSDSE-B の 47 都道府県・最新年度)── # skiprows=[1] で 2 行目(日本語の項目名)を飛ばし、英字の項目コードを列名にする import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == df['SSDSE-B-2026'].max()].copy() # 最新年度の 47 行 df['高齢化率'] = df['A1303'] / df['A1101'] * 100 # 65 歳以上人口 ÷ 総人口 import pandas as pd from scipy.cluster.hierarchy import linkage, fcluster, dendrogram, cophenet from scipy.spatial.distance import pdist from sklearn.preprocessing import StandardScaler import matplotlib.pyplot as plt # SSDSE-B-2026 に実在する 4 項目で「地域類型」を作る # A1101 総人口 / 高齢化率(上で導出) # L3221 消費支出(二人以上の世帯) … 家計の水準 # C5401 標準価格(平均価格)(住宅地) … 都市度 cols = ['A1101', '高齢化率', 'L3221', 'C5401'] X = df[cols].dropna() X_std = StandardScaler().fit_transform(X) Z = linkage(X_std, method='ward') df.loc[X.index, 'cluster'] = fcluster(Z, t=4, criterion='maxclust') # デンドログラムがもとの距離をどれだけ忠実に表しているか(コフェネティック相関) coph, _ = cophenet(Z, pdist(X_std)) print('リンク行列 Z.shape =', Z.shape) print('コフェネティック相関 =', round(coph, 3)) print(df.groupby('cluster')[cols].mean().round(1)) |
| クラスタ | 県数 | 総人口 A1101 | 高齢化率 % | 消費支出 L3221 | 住宅地標準価格 C5401 | 特徴 |
|---|---|---|---|---|---|---|
| 1 | 18 | 1,098,333 | 35.1 | 256,426 | 24,850 | 高齢化の進んだ小規模県 |
| 2 | 22 | 1,640,818 | 32.1 | 300,225 | 35,764 | 中規模の地方県 |
| 3 | 7 | 7,075,714 | 27.6 | 302,564 | 119,186 | 大都市圏 |
| 4 | 1 | 14,086,000 | 22.8 | 341,320 | 404,400 | 東京都(単独) |
SSDSE-B-2026(公的統計の社会・教育系データセット、 47 都道府県 × 10 年分超 × 100 以上の列)を用いて、 「Ward 法」を体感します。 ファイル名は SSDSE-B-2026.csv、 読み込みは下記の Python コードで行います。
🎯 このコードでやること:SSDSE-B-2026 を読み込み、最新年度の都道府県データから A1101(総人口)と A4101(出生数)を抽出して基本確認する。
📥 入力データ(SSDSE-B-2026 の先頭行イメージ):
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()) |
📤 実行すると次の出力が得られる:
💬 shape=(564,112) は 12 年分 × 47 都道府県。最新年度だけ取り出すと n=47 行になる。A1101 は総人口(人)、A4101 は出生数(人)。
ここで使った中心列 A1101 は SSDSE-B-2026 における 47都道府県を Ward 法で 4 クラスタに分割 に関連する指標です。 算出例:
A1101 平均と標準偏差を求めるA1101 と A4101 の相関(線形・順位)を比較するWard 法を素朴に実装すると、 クラスタ統合のたびに「すべてのペアのクラスタ内分散」を再計算することになり、 $O(n^3)$ で計算量が爆発する。 これを救うのが Lance-Williams 更新式。 クラスタ $A, B$ を統合して $A \cup B$ にしたとき、 他クラスタ $C$ との Ward 距離は
$$d(A\cup B, C) = \dfrac{n_A + n_C}{n_A + n_B + n_C}\,d(A,C) + \dfrac{n_B + n_C}{n_A + n_B + n_C}\,d(B,C) - \dfrac{n_C}{n_A + n_B + n_C}\,d(A,B)$$
で更新できる。 つまり 1 ステップ $O(n)$、 全体 $O(n^2)$ に落ちる。 これが scipy.cluster.hierarchy.linkage(method='ward') の高速化原理。
このコードでやること: SSDSE-B-2026 から「総人口(A1101)」「出生数(A4101)」「消費支出(L3221)」を取り、 Ward 法で 47 都道府県を 5 クラスタに分け、 各クラスタの代表都道府県と「統合直前の Ward 距離」を出力する。
📥 入力データ: SSDSE-B-2026 47 都道府県、 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 | # ── この抜粋で使うデータを用意します(英字の項目コードで読み込み)── import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=0) df = df[df['Code'].astype(str).str.match(r'^R\d{5}$', na=False)].copy() for _c in df.columns[3:]: df[_c] = pd.to_numeric(df[_c], errors='coerce') df = df[df['SSDSE-B-2026'] == df['SSDSE-B-2026'].max()] import pandas as pd from scipy.cluster.hierarchy import linkage, fcluster from sklearn.preprocessing import StandardScaler X = df[['A1101', 'A4101', 'L3221']].values Xs = StandardScaler().fit_transform(X) Z = linkage(Xs, method='ward') labels = fcluster(Z, t=5, criterion='maxclust') df['cluster'] = labels for c in sorted(df['cluster'].unique()): members = df[df.cluster==c]['Prefecture'].tolist() print(f"クラスタ{c} (n={len(members)}): {members[:3]}...") print(f"最後の統合距離 (Z末尾5行の3列目):") print(Z[-5:, 2]) |
📤 実行結果:
💬 結果の読み方: 東京都が n=1 の単独クラスタになり (クラスタ3)、 神奈川・愛知・大阪の 3 県が次のクラスタ (クラスタ1) — 都道府県データでは「規模で 2 極化」する Ward 法の特徴がそのまま出る。 残りは中規模 5 県・地方 24 県・過疎寄り 14 県に分かれた。 最後の統合距離を見ると 12.16 と 7.18 の間に大きなギャップがあり (直前の 4 つは 2.87→3.08→5.47→7.18 と緩やかに増える)、 これが「5 クラスタが妥当」のエルボー証拠。 ギャップの絶対値ではなく、 手前の増え方との落差を見るのがコツである。 単連結法ではこのギャップが消え、 鎖状クラスタ (chaining) が形成される — Ward が分散最小化により球状クラスタを優先する性質の現れ。
SSDSE-B-2026 を 47 都道府県 × 数値特徴量で階層クラスタリングするとき、 連結法 (linkage method) によってクラスタの形が大きく変わる。 Ward 法は「クラスタ内平方和の増加分を最小化する」基準のため、 球状で大きさが均等なクラスタを作りやすい。 以下に他法との差を整理する。
| linkage | 距離定義 | SSDSE-B での挙動 |
|---|---|---|
| Ward | 合併後の SSE 増分 ΔSSE 最小化 | 「東京単独」「大阪・愛知・神奈川」「地方中堅」「過疎県」のような球状クラスタ |
| single | 最近接点間距離 | chaining (鎖状連結) が起き、 巨大クラスタ + 孤立点に偏る |
| complete | 最遠点間距離 | 外れ値に弱く、 「東京」が単独クラスタとして孤立しがち |
| average | 全ペア平均距離 | Ward と single の中間で、 緩やかなクラスタを作る |
Ward 法を選ぶ判断軸: ① 各クラスタの「重心」を解釈に使う場合 (例: 「クラスタ 1 は人口 100 万前後、 消費支出 5 兆前後」)、 ② クラスタサイズの不均衡を避けたい場合、 ③ ユークリッド距離が自然な特徴量空間 (標準化済の数値変数)、 の 3 条件を満たす時。 SSDSE-B-2026 の都道府県分類はこの 3 条件を満たすため、 Ward が第一選択になる。
注意 — Ward は Euclidean 専用: scipy.cluster.hierarchy.linkage(method='ward') は内部でユークリッド距離を仮定する。 metric='cosine' 等と組み合わせると数学的に意味のないデンドログラムが出る。 距離尺度を変えたい時は average / complete に切り替えること。 また、 入力特徴量は 必ず標準化 しないと、 人口 (10⁶ オーダー) が距離を支配し他の変数が無視される。
🎯 このコードでやること:同じ標準化データに k-means と Ward 法(AgglomerativeClustering)を当てはめ、シルエット係数でクラスタリング品質を比較する。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2)
# 47都道府県を高齢化率・所得・人口で Ward 法クラスタリング
# 入力 X(標準化済み, shape=(47, 3)):
# pref z_age z_inc z_pop
# 0 北海道 0.31 -0.42 0.85
# 1 青森県 1.45 -1.21 -0.62
# 2 岩手県 1.39 -0.72 -0.68
# 3 宮城県 -0.23 0.18 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}') |
🎯 このコードでやること:k を 2〜10 まで動かし、エルボー法(inertia)とシルエット係数の 2 指標で最適クラスタ数を探索する。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2)
# 47都道府県を高齢化率・所得・人口で Ward 法クラスタリング
# 入力 X(標準化済み, shape=(47, 3)):
# pref z_age z_inc z_pop
# 0 北海道 0.31 -0.42 0.85
# 1 青森県 1.45 -1.21 -0.62
# 2 岩手県 1.39 -0.72 -0.68
# 3 宮城県 -0.23 0.18 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') |
🎯 このコードでやること:Ward 法のリンク行列 Z からデンドログラム(樹形図)を描画し、どの高さで切ると何クラスタになるかを可視化する。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2)
# 47都道府県を高齢化率・所得・人口で Ward 法クラスタリング
# 入力 X(標準化済み, shape=(47, 3)):
# pref z_age z_inc z_pop
# 0 北海道 0.31 -0.42 0.85
# 1 青森県 1.45 -1.21 -0.62
# 2 岩手県 1.39 -0.72 -0.68
# 3 宮城県 -0.23 0.18 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() |
scipy.cluster.hierarchy(教育用に推奨)🎯 このコードでやること:scipy.cluster.hierarchy で linkage → fcluster → dendrogram を実行する、教育用に最も基本的な Ward 法の書き方。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2)
# 47都道府県を高齢化率・所得・人口で Ward 法クラスタリング
# 入力 X(標準化済み, shape=(47, 3)):
# pref z_age z_inc z_pop
# 0 北海道 0.31 -0.42 0.85
# 1 青森県 1.45 -1.21 -0.62
# 2 岩手県 1.39 -0.72 -0.68
# 3 宮城県 -0.23 0.18 0.211 2 3 4 | from scipy.cluster.hierarchy import linkage, fcluster, dendrogram Z = linkage(X_std, method='ward') clusters = fcluster(Z, t=4, criterion='maxclust') dendrogram(Z, labels=df['Prefecture'].tolist(), leaf_rotation=90) |
sklearn.cluster.AgglomerativeClustering(Pipeline 向け)🎯 このコードでやること:sklearn.cluster.AgglomerativeClustering(linkage="ward") でクラスタラベルを直接得る、Pipeline に組み込みやすい書き方。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2)
# 47都道府県を高齢化率・所得・人口で Ward 法クラスタリング
# 入力 X(標準化済み, shape=(47, 3)):
# pref z_age z_inc z_pop
# 0 北海道 0.31 -0.42 0.85
# 1 青森県 1.45 -1.21 -0.62
# 2 岩手県 1.39 -0.72 -0.68
# 3 宮城県 -0.23 0.18 0.211 2 3 4 | from sklearn.cluster import AgglomerativeClustering agg = AgglomerativeClustering(n_clusters=4, linkage='ward') labels = agg.fit_predict(X_std) print(labels[:10]) |
fastcluster(大規模データ・C++ 実装)🎯 このコードでやること:fastcluster.linkage_vector を使い、数千点規模でも scipy より高速に Ward 法のリンク行列を計算する。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2)
# 47都道府県を高齢化率・所得・人口で Ward 法クラスタリング
# 入力 X(標準化済み, shape=(47, 3)):
# pref z_age z_inc z_pop
# 0 北海道 0.31 -0.42 0.85
# 1 青森県 1.45 -1.21 -0.62
# 2 岩手県 1.39 -0.72 -0.68
# 3 宮城県 -0.23 0.18 0.211 2 | import fastcluster Z = fastcluster.linkage_vector(X_std, method='ward') # 数千点規模で scipy より高速 |
🎯 このコードでやること:同じリンク行列 Z に対して fcluster の t(クラスタ数)を 2〜9 で変え、シルエット係数が最大になる k を選ぶ。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2)
# 47都道府県を高齢化率・所得・人口で Ward 法クラスタリング
# 入力 X(標準化済み, shape=(47, 3)):
# pref z_age z_inc z_pop
# 0 北海道 0.31 -0.42 0.85
# 1 青森県 1.45 -1.21 -0.62
# 2 岩手県 1.39 -0.72 -0.68
# 3 宮城県 -0.23 0.18 0.211 2 3 4 5 | from sklearn.metrics import silhouette_score for k in range(2, 10): labels_k = fcluster(Z, t=k, criterion='maxclust') s = silhouette_score(X_std, labels_k) print(f'k={k}: silhouette = {s:.3f}') |
🎯 このコードでやること:seaborn.clustermap でヒートマップと Ward 法のデンドログラムを同時に描き、変数×都道府県のパターンを一望する。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=2)
# 47都道府県を高齢化率・所得・人口で Ward 法クラスタリング
# 入力 X(標準化済み, shape=(47, 3)):
# pref z_age z_inc z_pop
# 0 北海道 0.31 -0.42 0.85
# 1 青森県 1.45 -1.21 -0.62
# 2 岩手県 1.39 -0.72 -0.68
# 3 宮城県 -0.23 0.18 0.211 2 3 4 5 6 7 8 9 10 11 12 13 | # ── この抜粋で使うデータを用意します(SSDSE-B の 47 都道府県・最新年度)── import pandas as pd from sklearn.preprocessing import StandardScaler df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == df['SSDSE-B-2026'].max()].copy() df['高齢化率'] = df['A1303'] / df['A1101'] * 100 X = df[['A1101', '高齢化率', 'L3221', 'C5401']].dropna() X_std = StandardScaler().fit_transform(X) import seaborn as sns sns.clustermap(pd.DataFrame(X_std, index=df.loc[X.index, 'Prefecture'], columns=X.columns), method='ward', cmap='RdBu_r', center=0) |
scipy / pandas / scikit-learn / statsmodels を中心とした標準的な実装例です。 まず CSV を読み込み、 次に Ward 法 の解析を行います。
🎯 このコードでやること:SSDSE-B-2026 の最新年度データを読み込み、A1101(人口)と A4101(出生数)の基本統計量・相関を計算する。Ward 法クラスタリングの前処理として使う。
📥 入力データ(SSDSE-B-2026 最新年度、n=47):A1101、A4101 の 2 列
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)) # Ward 法 の代表的計算(用途に応じて 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}') |
📤 実行すると次の出力が得られる:
💬 人口と出生数の Pearson 相関が r=0.995 と極めて高い。Ward 法でクラスタリングする前に標準化(StandardScaler)が必要。
用途別の追加実装:
🎯 このコードでやること:標準化した 2 変数で Ward 法(k-means 比較用)を実行し、4 クラスタのラベルと各都道府県の所属を確認する。
📥 入力データ:上記コードで生成した標準化済み Xs(shape=(47,2))
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)) |
📤 実行すると次の出力が得られる:
💬 人口規模で明瞭に分かれ、北海道など人口の多い県が別クラスタになる。k=4 だと東京など超大都市を独立クラスタに分離できる(クラスタ番号は初期値依存で意味は任意)。
🎯 このコードでやること:SSDSE-B-2026 の全都道府県時系列で A1101 の推移を確認し、ADF 検定で定常性を調べる(Ward 法クラスタリング前の時系列補足分析)。
📥 入力データ:全年度の SSDSE-B-2026(A1101 列)
1 2 3 4 5 6 7 8 9 10 11 | # 時系列(全国平均の A1101)— 例として ARIMA 系の前処理 # ここでは年度を絞らずに全 12 年度を読む(1 年度だけだと系列にならない) import pandas as pd import statsmodels.api as sm df_all = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) ts = df_all.sort_values('SSDSE-B-2026').groupby('SSDSE-B-2026')['A1101'].mean() print(ts.tail().round(1)) res = sm.tsa.stattools.adfuller(ts) print('ADF stat:', round(res[0], 3), ' p:', round(res[1], 3)) |
📤 実行すると次の出力が得られる:
💬 全国平均人口(47 都道府県の平均、 単位は人)は単調減少トレンド。ADF の p=0.976 は「単位根あり(非定常)」をまったく棄却できないことを示す。Ward 法での横断面クラスタリングは各年度の「スナップショット」として有効。
階層クラスタリング全般(デンドログラムの読み方など)は 階層クラスタリング・デンドログラム のページで扱いました。 ここでは Ward 法「固有」の性質に絞ります:併合候補ペアごとにクラスタ内分散(SSE)の増分 ΔE を全部計算し、 ΔE が最小のペアを選ぶ——このルールだけで、 なぜ「球状・同サイズ」のクラスタができるのか。 単連結(最短距離)との併合順の違いを並べて体感してください。
🖱️ 点はドラッグで自由に動かせます(タッチ対応)。 動かすと両方の併合順・ΔE 一覧・SSE 推移が即座に再計算されます。 ΔE は Lance-Williams 漸化式(初期値 $d_{ij}=\tfrac{1}{2}\lVert x_i-x_j\rVert^2$)で正確に計算しています。
破線=次に併合されるペア(Ward は重心間、 単連結は最近接点間)。 色付きの領域=現在のクラスタ。
左端=全点バラバラ(SSE=0)、 右端=1クラスタ。 同じクラスタ数 k なら Ward の方が総 SSE が小さい(=まとまりが良い)ことが多い。 縦の点線=現在のステップ。
2 クラスタ $A,B$ を併合したときの SSE 増分は、 展開すると次のきれいな形になります:
$\Delta E(A,B) = \dfrac{n_A\, n_B}{n_A + n_B}\, \lVert \mu_A - \mu_B \rVert^2$
読み方は 2 つの因子に分ければ簡単です:
上のデモで「⛓️ 鎖状」を選んで見比べると、 単連結は端から 1 点ずつ鎖を伸ばす(最短距離しか見ないので、 隣さえ近ければどんどん繋がる)のに対し、 Ward は鎖をいくつかの塊に切り分けてから塊同士を併合します。 ΔE ランキングの表で、 大きくなったクラスタが候補の下位に沈んでいく様子を確認してください。 これが「球状・同サイズ」バイアスの正体です。
hclust には ward.D と ward.D2 があります。 本来の Ward 法は二乗ユークリッド距離で Lance-Williams を回すもの(このデモの実装、 ward.D2 や scipy の method="ward" 相当)。 ward.D は「二乗していない距離」に同じ漸化式を当てた歴史的な亜種で、 併合順が変わりえます。 論文で「Ward 法」とだけ書かれていたら、 どちらの実装かを確認するのが安全です(Murtagh & Legendre 2014)。hclust(method="ward.D") と method="ward.D2" は微妙に違います。 ward.D2 が正式な Ward 法。 Python の scipy はデフォルトで ward.D2 相当。 R を使うなら ward.D2 を指定する。1. 標準化を忘れる。所得(千円単位)と高齢化率(%)を同じスケールで距離計算すると、 桁の大きい所得だけが結果を支配します。 StandardScaler で z スコア化するか、 MinMaxScaler で [0,1] に揃えてから linkage に投入しましょう。
2. ユークリッド距離以外を使う。Ward 法の数学的根拠は二乗ユークリッド距離に基づく分散分解です。 マンハッタンやコサインを scipy.spatial.distance で渡しても、 数式の整合性が壊れ、 結果の解釈ができなくなります。 別距離なら average や complete linkage を使いましょう。
3. クラスタ数の決定基準を持たない。「デンドログラムを見て直感で 4 個」だと再現性が無くなります。 シルエット係数・Calinski-Harabasz・Gap statistic・NbClust 風のスコア群を併用し、 複数指標で 4±1 程度の幅で議論するのが論文では好まれます。
4. 球形でないクラスタに無理に Ward を適用する。三日月型・らせん型のデータを Ward で分けると、 直感に反する分裂が起きます。 DBSCAN・OPTICS・スペクトラルクラスタリングの方が向く問題群が存在することを知っておきましょう。
5. 外れ値の影響を過小評価する。1 県だけが極端な値を持つと(例:東京の人口密度)、 ツリーが初期段階で「東京+その他」の 2 分割になり、 残りの解像度が落ちます。 robust スケール化(中央絶対偏差 MAD)や対数変換を検討しましょう。
6. 「クラスタ=因果カテゴリ」と思い込む。Ward 法は単なる類似度の階層分割であり、 そのクラスタが「政策効果が同じ」「介入応答が同じ」とは限りません。 クラスタを使った下流分析(処置効果・予測)はあくまで仮説生成に留めるのが安全です。
7. 元データに欠損があるまま投入する。SciPy の linkage は NaN を含むと内部でエラーになるか、 距離が NaN になり結果が破綻します。 SimpleImputer や KNNImputer での欠損補完を必ず先に行い、 補完の妥当性を別途検証しましょう。
Ward 法 を実務で扱う際に踏みやすい落とし穴を 5 件挙げます。
Ward法 がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。
▲ JS 不要の静的 SVG 概念マップ。Ward 法の位置付け・前提・並列手法・下流応用を一望できる。
🌐 統計・データサイエンス › 教師なし学習 › クラスタリング › Ward法
中心に Ward法 を置き、 そこから 階層クラスタリング・分散・標準化・デンドログラム・クラスタリング全般・k-means など 計 12 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語とあとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。
大きな円が小さな円を包含する Circle Packing 図。 「Ward法」は緑色でハイライト。
長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「Ward法」は緑色でハイライト。
| マップ | 分かること | こんな時に見る |
|---|---|---|
| 🔗 関係マップ | 手法間の横の関係(前提→発展→応用) | 「次に何を学べばよい?」 学習順序の判断 |
| ⭕ 包含マップ | 分類体系の入れ子構造(上位⊃下位) | 「この手法はどんなジャンルに属する?」 |
| 🌳 ツリーマップ | 分野の規模比較(面積=ボリューム) | 「データサイエンス全体の俯瞰像」 |
💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは Ward法 の隣に何が並ぶかを、 包含マップとツリーマップは 統計・データサイエンス → クラスタリング → Ward法 という入れ子の位置を示します。 「クラスタリングには他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。
Ward 法は階層的クラスタリングの 1 連結方式であり、 前処理 (標準化) と評価 (デンドログラム / シルエット) の組み合わせで完成する。 以下は典型的な接続パターン。
| 位置 | 手法・概念 | 接続の意味 |
|---|---|---|
| 上流(前処理) | 標準化 / PCA | Ward 法の前に必ず標準化。 高次元データは PCA で次元削減してから投入することも有効。 |
| 並列(代替) | k-means / DBSCAN | Ward は階層構造の可視化が強み。 k が決まっているなら k-means、 密度ベースなら DBSCAN。 |
| 下流(評価) | シルエット係数 / デンドログラム | Ward の出力はデンドログラムで切断高さを選択。 シルエット係数で最適 k を定量評価。 |
これらの接続を意識することで、 「Ward法 (Ward's Method)」を中核に据えた一貫した分析パイプラインを構築できる。
下記のフローに従って「Ward 法が適切か」を判定する。
| 判定条件 | YES → 次へ | NO → 代替手法 |
|---|---|---|
| ① データは連続数値変数か? | ② へ | カテゴリ変数なら k-modes、 混合なら Gower 距離 + complete |
| ② ユークリッド距離が自然か?(単位を揃えれば等方的) | ③ へ | テキスト・ネットワーク → コサイン/グラフ距離 + average/complete |
| ③ n < 5,000 程度か? | ④ へ | 大規模データ → BIRCH → Ward の 2 段構成、 または HDBSCAN |
| ④ クラスタ数を事前に決めずに探索したいか? | Ward 法を選択 | クラスタ数が決まっているなら k-means の方が速い |
| ⑤ クラスタが球状・均等サイズを期待するか? | Ward 法が第一選択 | 細長い・リング状クラスタ → single / DBSCAN / Spectral |
💡 SSDSE-B-2026 の 47 都道府県 × 数値特徴量は条件①〜⑤をすべて満たす → Ward 法が第一選択。
ここまでの解説は「Ward 法はこう振る舞うはず」という一般論が中心でした。 この節では、 SSDSE-B-2026 の 2023 年度・47 都道府県の実データに Ward 法を実際に適用し、 教科書的な主張がどこまで成り立ち、 どこで裏切られるかを実測値だけで確かめます。 使用した 4 指標はすべて実在列からの導出です:
各指標を z 標準化してから scipy.cluster.hierarchy.linkage(X, method="ward") を実行した実測結果が以下です。
Ward 法のデンドログラムの縦軸(併合高さ)は「その併合で払った SSE 的コスト」。 実測した最後の 6 回の併合高さは次の通りでした:
| 併合 | k=7→6 | k=6→5 | k=5→4 | k=4→3 | k=3→2 | k=2→1 |
|---|---|---|---|---|---|---|
| 高さ(実測) | 3.235 | 3.441 | 4.132 | 4.447 | 7.198 | 13.584 |
→ 4.447 から 7.198 へと約 1.6 倍に跳ねる直前、 つまり「k=3 で切る」あたりが階段の折れ目。 最後の併合はさらに 13.584 まで跳ね(1.9 倍)、 これが「東京を含む一群と残り」を分ける線に対応する。 デンドログラムを眺めて「なんとなく 4 つ」ではなく、 併合高さの数列の跳躍として k を根拠づけられます。 実際に k=4 で切った実測クラスタは次の通り(括弧内はクラスタ平均:高齢化率% / 転入超過率 / 出生率 / 気温℃):
落とし穴 1:標準化を忘れた Ward 法は「人口の輪切り」になる(実測)。 総人口 A1101(標準偏差 ≈ 276.8 万人)と合計特殊出生率 A4103(標準偏差 ≈ 0.132)を標準化せずに混ぜて Ward 法を実行すると、 標準偏差の比は約 2,100 万倍。 実測の k=4 の結果は「東京だけ(1)/埼玉・神奈川・愛知・大阪(4)/北海道・千葉・兵庫・福岡(4)/残り 38 県」— つまりただの人口ランキングの輪切りで、 出生率の情報は完全に消えます。 標準化した場合との調整ランド指数(ARI)は実測 0.177。 ほぼ別物の分類になるという事実を、 数字で覚えておいてください。
落とし穴 2:「均等サイズになりやすい」は傾向であって保証ではない(実測)。 本文の比較表では Ward 法の長所として「均等サイズ」を挙げていますが、 上の実測 k=4 は 24 / 14 / 8 / 1 と大きく不均等で、 沖縄は単独クラスタです。 Ward 法は「単連結ほど極端な偏りを作りにくい」だけで、 データに実在する外れ構造(沖縄のような別格の県)はきちんと単独で切り出します。 むしろ「1 県クラスタが出た=その県が多変量的な外れ値」というシグナルとして読むのが実務的です。
デンドログラムの忠実度指標であるコフェネティック相関(元のペア距離と樹形図上の距離の相関)を、 同じ標準化済みデータで 4 つの連結法について実測すると:
| 連結法 | Ward | 単連結 | 完全連結 | 群平均 |
|---|---|---|---|---|
| コフェネティック相関(実測) | 0.669 | 0.723 | 0.529 | 0.789 |
→ 「第一選択」のはずの Ward 法 (0.669) は群平均 (0.789)・単連結 (0.723) に及ばず4 手法中 3 位、 群平均が最上位です。 これは矛盾ではありません。 コフェネティック相関は「元の距離をどれだけ保存するか」を測る指標で、 群平均連結はまさに距離の平均を保つよう設計されているため高くなりやすい。 一方 Ward 法は距離保存ではなくクラスタ内 SSE の最小化を目指すため、 樹形図の高さが SSE 増分に置き換わり、 元の距離との相関は下がります。 つまり「良いクラスタリング」の定義は指標ごとに違う — 分割の解釈しやすさなら Ward、 距離構造の忠実な要約なら群平均、 と目的で使い分けるのが発展的な理解です。 なお本ページ上部の実行例にあるコフェネティック相関と値が異なるのは、 使用する変数セットが異なるためで、 この指標は変数構成に強く依存します(より正確には、 併記した導出式の 4 指標での実測値が上表です)。