クラスタリング 関連の補強キーワード。 クリックで該当箇所へ:
「クラスタリング」を理解するうえで必要なキーワードを 10 件以上提示します。 各チップから対応セクションへ移動できます。
30 秒結論 文脈 直感 数式 記号読み解き 実値計算 Python 実装 落とし穴 関連手法 関連用語 グループ教材 概念マップ
🍰 まずはやさしく
似たもの同士を分けるグループ分けです。
データの自然なまとまりを見つけるために使います。
スマホのアプリで好みの曲を分けるようなものです。
ここでは代表的なやり方や注意点を読みます。
sklearn.cluster に各種手法が実装されているクラスタリング(clustering)は、 「似たサンプル同士を自動でグループ化する」教師なし学習の代表的タスク。 「正解ラベル」を一切与えず、 データの内部構造をアルゴリズムが自力で発見します。
教師あり学習との違い:
クラスタリングは「データの中に自然なグループはあるか?あるならどんな?」という探索的な問いに使います。 正解がないので、 結果の「正しさ」を評価するのが難しい一方、 仮説生成・データの初期理解で強力な道具になります。
クラスタリング手法は次の4大カテゴリに分かれます:
| 分類 | 仕組み | 代表例 | 向くデータ |
|---|---|---|---|
| 分割型(partitional) | k個の中心への距離で分割 | k-means, k-medoids | 球形クラスタ、 大規模 |
| 階層型(hierarchical) | 点を段階的に結合 or 分割 | Ward法, 単連結, 完全連結 | 中規模、 階層構造あり |
| 密度ベース | 密な領域をクラスタとみなす | DBSCAN, OPTICS, Mean Shift | 非球形、 ノイズあり |
| モデルベース | 確率分布の混合と仮定 | GMM, EM, ベイズクラスタ | 確率的所属、 重なり許容 |
クラスタリングの中核は「2つのサンプルがどれだけ似ているか」の数値化。 これを「距離」(または類似度)と呼びます:
選択の指針:
単位の違う変数を混ぜると、 桁の大きい変数だけで距離が決まり、 他の変数の情報が消えます。 例えば「人口(万人)」と「失業率(%)」をユークリッド距離で測れば、 人口の差が圧倒的に大きいため、 結果は実質「人口」だけでクラスタリングしたものに。
対策:必ず標準化(z-score化)してから距離計算。 sklearn.preprocessing.StandardScaler で平均0・分散1に揃える。 これで全変数が「平等」に効く。
k-means のような分割型では「何個のクラスタに分けるか」を事前に決める必要があります。 客観的指標:
「死亡率」「高齢化率」「保健医療費」「転入率」の4変数で47都道府県を k-means(k=4)でクラスタリングすると、 典型的に次のような結果になります:
これがクラスタリングの典型的な使い方。 「データ駆動で47都道府県を4類型に分類した」という客観的根拠として、 政策資料に使えます。
「正解」がないので、 結果の良さを評価するのが難しい。 主な評価手法:
内部評価(ラベルなしで評価):
外部評価(真のラベルがある場合):
解釈の難しさ:クラスタが見つかっても、 「なぜそうグルーピングされたか」「各クラスタの特徴は何か」は別途分析が必要。 クラスタごとの変数の平均値・標準偏差・代表サンプルを確認するのが定石。
🍰 まずはやさしく
データの共通点を探す分析手法のことです。
正解がないデータからグループを作りたいときに使います。
都道府県を特徴で分けるときなどに役立ちます。
この手法が分析の中でどう使われるかを読みます。
論文で「クラスタリング」「クラスタ分析」「教師なし学習で分類」と書かれているとき。 「47都道府県を似ているグループに自動分類」「顧客を購買行動で分類」など、 ラベルなしデータから自然なグループ構造を発見する手法の総称。
クラスタリング とは:教師ラベルなしで、似たサンプル同士をグループ(クラスタ)に分ける手法の総称。
本ページは クラスタリング を、 統計データ分析コンペティション 2026 の再現教材として整理した用語ページです。 中核用語のひとつで、 47都道府県の人口・高齢化率・消費支出を用いたクラスタ分析 という具体的観点で SSDSE-B-2026(47 都道府県 × 複数年 × 100 超列)に紐づき、 実データを使って手を動かしながら理解できる構成にしています。
位置づけ:相関・線形回帰・仮説検定 といった基礎用語群と並列であり、応用としては 内生性・IV・DID・クラスタリング 等へ繋がります。
🍰 まずはやさしく
データから自然なグループを作るイメージです。
データの傾向を分かりやすく整理するために使います。
部活のメンバーを能力や性格で分けるようなものです。
状況に合わせて手法を選ぶ流れについて読みます。

図は典型的なクラスタリング結果。 4つの「自然なグループ」がデータから自動的に発見されています。 各クラスタには地理的・経済的に類似した県が集まり、 「データ駆動の分類」として解釈可能。
大事なポイント:このクラスタは「用意した変数(死亡率、 高齢化率)に基づく類似度」での分類。 違う変数(例えば気温や産業構造)で実行すれば、 違う分類が出ます。 「絶対的な真の分類」ではなく、 「分析者の選択を反映した類型化」なのが本質。
「どの手法を使うべきか」迷ったときの判断フロー:
① クラスタ数が事前に決まっているか?
② データの形状は球形に近いか?
③ ノイズや外れ値が多いか?
④ サンプル数は?
⑤ 結果の階層構造を見たいか?
⑥ 確率的な所属(「東京は60%大都市、 40%中核」)が欲しいか?
1つの手法だけで結論を出さず、 複数手法で結果を比較し、 安定して同じグループが出るなら信頼性が高い。 「k-means と Ward法 で同じクラスタ構造が見えた」のような頑健性チェックが論文の品質を上げます。
クラスタリングには本質的な限界もあります:
これらの限界を意識した上で、 「データを整理する道具」として使うのが正しい使い方。 「客観的真実を発見する魔法」ではない。
クラスタリング を一言でいえば「47都道府県の人口・高齢化率・消費支出を用いたクラスタ分析」。 47 都道府県という小さな母集団でも、 SSDSE-B-2026 の A1101 列に注目すると、 大都市圏と地方の差・人口規模に伴う相対比較など、 様々なパターンが見えてきます。
比喩でいうと、 クラスタリング はデータ分析の「眼鏡」のようなもの。 同じデータでも眼鏡を変えれば、 平均(中心)・分散(ばらつき)・相関(連動)・因果(影響)と、 異なる情報が浮かび上がります。 SSDSE-B-2026 を題材に、 この眼鏡をかけてみるのが本ページの狙いです。
🍰 まずはやさしく
似ている点同士を同じ群に分ける計算です。
「似ている」ことを数値で表すために使います。
買い物での支出額が近い人をまとめるようなものです。
計算の仕組みや距離の測り方について読みます。
クラスタリングは「データ点の集合 $\{x_1, ..., x_n\}$ を、 互いに似た点が同じ群に入るように $K$ 個のクラスタ $C_1, ..., C_K$ に分割する」問題。 「似ている」の数値化 (距離) と「最適化目的」(評価指標) の組合せが手法を決める。
最も基本的な分割型クラスタリング(詳細は k-means法 のページ参照)。 各クラスタ $C_k$ の中心 $\mu_k$ と所属点の距離二乗和 (SSE; Sum of Squared Errors) を最小化:
$$ \arg\min_{\{C_k\},\{\mu_k\}} \sum_{k=1}^K \sum_{x \in C_k} \lVert x - \mu_k \rVert^2 \quad \text{where} \quad \mu_k = \frac{1}{|C_k|} \sum_{x \in C_k} x $$$\mu_k$ はクラスタ $k$ の重心 (centroid)。 反復で「最近傍割当て → 重心更新」を繰り返す (Lloyd アルゴリズム)。
「2 点間がどれだけ似ているか」を測る距離 $d(x, y)$ の代表例:
2 つのクラスタ $A, B$ 間の距離 $D(A, B)$ をどう定義するかでアルゴリズムが分かれる(詳細は 階層クラスタリング・Ward法・デンドログラム の各ページ参照):
点 $p$ を中心とする半径 $\varepsilon$ の球内に $\text{MinPts}$ 個以上の点が含まれるとき、 $p$ を コア点 (core point) と呼ぶ:
$$ N_\varepsilon(p) = \{q \mid d(p, q) \leq \varepsilon\}, \quad |N_\varepsilon(p)| \geq \text{MinPts} \implies p \in \text{Core} $$コア点同士が密度到達可能 (density-reachable) なら同じクラスタ。 いずれのコア点からも到達できない点はノイズ (外れ値) 扱い。
結果クラスタリングの良さを定量化する代表的指標:
$K$ 個の多変量正規分布の混合として、 各点の所属を確率で表す:
$$ p(x) = \sum_{k=1}^K \pi_k\, \mathcal{N}(x \mid \mu_k, \Sigma_k), \quad \sum_{k=1}^K \pi_k = 1 $$$\pi_k$ は事前確率、 $\Sigma_k$ は共分散行列。 EM アルゴリズムで最尤推定。 ベイズの定理で各点 $x$ の所属確率 (responsibility) を計算: $$ \gamma_k(x) = \frac{\pi_k\, \mathcal{N}(x \mid \mu_k, \Sigma_k)}{\sum_{j=1}^K \pi_j\, \mathcal{N}(x \mid \mu_j, \Sigma_j)} $$
k-means は GMM で $\Sigma_k = \sigma^2 I$ (等方分散) かつ硬い割当 ($\gamma_k \in \{0,1\}$) とした特殊ケース。
これら 6 種の数式群を理解すれば、 「何を最小化しているか」「どの仮定が崩れたら別手法に切り替えるか」という選択判断が可能になる。 詳細な記号解説は次節で行う。
前節の数式に登場した各記号を、日本語の意味に変換します。
47 都道府県を経済指標 5 次元でクラスタリングし、 地域類型を抽出する完全例。 標準化+ k-means/階層/DBSCAN を比較。
🎯 このコードでやること:クラスタリング — 教師なし学習による群構造発見に関連するステップ #4。主要な指標(係数・統計量・スコア)を算出します。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県
# 総人口・高齢化率・消費支出・診療所数(人口10万対)・標準地価 の5指標でクラスタリング
# 標準化後の X (shape=(47, 5)):
# pref A1101 高齢化率 消費支出 診療所数 C5401
# 0 北海道 0.88 0.43 0.04 -1.50 -0.49
# 1 青森県 -0.53 1.10 -1.36 -1.08 -0.61
# 2 岩手県 -0.54 1.03 0.11 -0.76 -0.451 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 | import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans, AgglomerativeClustering, DBSCAN from sklearn.preprocessing import StandardScaler from sklearn.metrics import silhouette_score from sklearn.decomposition import PCA df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True) # 2023年度の47都道府県 df['高齢化率'] = df['A1303'] / df['A1101'] * 100 # 高齢人口 / 総人口 (%) df['消費支出'] = df['L3221'] / 1000 # 二人以上の世帯、 千円/月 df['診療所数'] = df['I5102'] / df['A1101'] * 100000 # 人口10万人あたり features = ['A1101', '高齢化率', '消費支出', '診療所数', 'C5401'] # A1101=総人口、 C5401=標準地価 X = StandardScaler().fit_transform(df[features]) # エルボー法 inertias, silhouettes = [], [] ks = range(2, 11) for k in ks: km = KMeans(n_clusters=k, random_state=42, n_init=10).fit(X) inertias.append(km.inertia_) silhouettes.append(silhouette_score(X, km.labels_)) fig, axes = plt.subplots(1, 2, figsize=(11, 4)) axes[0].plot(ks, inertias, 'o-'); axes[0].set_xlabel('k'); axes[0].set_ylabel('Inertia (SSE)') axes[1].plot(ks, silhouettes, 'o-'); axes[1].set_xlabel('k'); axes[1].set_ylabel('Silhouette') plt.tight_layout(); plt.savefig('cluster_elbow.png', dpi=110) # シルエット最大は k=2 だが、 解釈しやすさから k=4 で確定 km = KMeans(n_clusters=4, random_state=42, n_init=10).fit(X) df['cluster'] = km.labels_ print('クラスタごとの代表値:') print(df.groupby('cluster')[features].mean().round(1)) |
📤 実行例(実行時の標準出力)
クラスタごとの代表値:
A1101 高齢化率 消費支出 診療所数 C5401
cluster
0 1003076.9 34.4 271.9 92.6 25023.1
1 14086000.0 22.8 341.3 105.7 404400.0
2 6374750.0 27.1 296.1 79.2 112800.0
3 1849160.0 31.9 306.4 81.1 37436.0| 項目 | 値 | 参考 | 解釈 |
|---|---|---|---|
| k | Inertia | Silhouette | 解釈 |
| 2 | 153.3 | 0.488 | 都市圏/地方 二分(シルエット最大) |
| 3 | 119.5 | 0.248 | 都市/中間/地方 |
| 4 | 89.1 | 0.268 | 採用(解釈しやすさ重視) |
| 5 | 74.3 | 0.272 | 細分化(過剰) |
| クラスタ0 | 青森・秋田・島根 など計13県 | 高高齢化・低地価 | 高齢化地方群 |
| クラスタ1 | 東京都(単独) | 超高地価・低高齢化 | 大都市 |
| クラスタ2 | 神奈川・大阪・福岡 など計8府県 | 高人口・高地価 | 大都市圏 |
| クラスタ3 | 北海道・宮城・広島 など計25道府県 | 各指標が中位 | 中間群 |
👉 値は SSDSE-B-2026(2023年度)に上記コードを実行した実測値。 同じ手順で他年度・他変数にも適用可能。
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 の相関(線形・順位)を比較する合成データ 3 点と初期重心 (3,3) を代入し、 k-means の重心更新式 c_k = (1/|C_k|) Σ x_i を Step 1〜4 で 1 step ぶん手計算する。 同じ計算を Python(scikit-learn)で再現し、 結果が完全一致することを確認する。
$$ c_k \;=\; \frac{1}{|C_k|}\sum_{x_i \in C_k} x_i, \qquad d(x_i, c_k) = \sqrt{\sum_j (x_{ij} - c_{kj})^2} $$
c_k はクラスタ k の重心、 C_k はクラスタ k に割り当てられた点集合。 各点を最近傍重心に割り当て、 重心を再計算するのが 1 step。
| 点 | x | y |
|---|---|---|
| P1 | 2 | 3 |
| P2 | 4 | 5 |
| P3 | 7 | 8 |
| 初期重心 c | 3 | 3 |
k=1(重心 1 個)の最小例。 すべての点が唯一のクラスタに属する。
| 点 | 計算(ユークリッド距離) | 結果 |
|---|---|---|
| P1→c | √((2-3)² + (3-3)²) = √1 | 1.0000 |
| P2→c | √((4-3)² + (5-3)²) = √5 | 2.2361 |
| P3→c | √((7-3)² + (8-3)²) = √41 | 6.4031 |
距離は割当てには使わない(k=1 なので全点同一クラスタ)が、 重心が初期位置からどれだけ動くかの直感を与える。
| 成分 | 計算 | 結果 |
|---|---|---|
| 新重心 c_x | (2 + 4 + 7) / 3 | 4.3333 |
| 新重心 c_y | (3 + 5 + 8) / 3 | 5.3333 |
| 新重心 c' | (4.3333, 5.3333) | — |
| 項目 | 計算 | 結果 |
|---|---|---|
| 重心移動量 | √((4.3333-3)² + (5.3333-3)²) = √(1.7778+5.4445) | 2.6874 |
| SSE = Σ d(x_i, c')² | (2-4.3333)²+(3-5.3333)² + (4-4.3333)²+(5-5.3333)² + (7-4.3333)²+(8-5.3333)² | 25.3333 |
重心が (3,3) から (4.33, 5.33) へ約 2.69 移動。 SSE は 25.33(= 5.4444+5.4444+0.1111+0.1111+7.1111+7.1111)で、 これが次の step(k=1 だと最終)の目的関数値。
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 | import numpy as np from sklearn.cluster import KMeans # Step 1: データ X = np.array([[2,3], [4,5], [7,8]]) c_init = np.array([[3,3]]) # Step 2: 初期重心までの距離(手計算照合) d = np.linalg.norm(X - c_init, axis=1) print(f"初期重心までの距離: {d.round(4).tolist()}") # Step 3: 新重心(k=1 なので単純平均) c_new = X.mean(axis=0) print(f"新重心 c' = {c_new}") # Step 4: 移動量と SSE shift = np.linalg.norm(c_new - c_init[0]) sse = ((X - c_new)**2).sum() print(f"重心移動量 = {shift:.4f}") print(f"SSE = {sse:.4f}") # sklearn KMeans で同等確認(k=1、 初期重心 (3,3)) km = KMeans(n_clusters=1, init=c_init, n_init=1, max_iter=1, random_state=0) km.fit(X) print(f"KMeans 収束後重心: {km.cluster_centers_}") print(f"KMeans inertia (SSE): {km.inertia_:.4f}") |
💬 手計算(Step 2: 距離 1.0/2.236/6.403、 Step 3: 重心 (4.333, 5.333)、 Step 4: 移動量 2.687, SSE 25.333)と numpy 出力・sklearn KMeans の収束結果がすべて完全一致。 k-means の 1 step は「最近傍割当て → 重心平均」の単純反復であることが体感できる。
🎯 このコードでやること:クラスタリング — 教師なし学習による群構造発見に関連するステップ #1。最初のスニペットです。SSDSE-B-2026 を読み込みます。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県
# 総人口・高齢化率・消費支出・診療所数(人口10万対)・標準地価 の5指標でクラスタリング
# 標準化後の X (shape=(47, 5)):
# pref A1101 高齢化率 消費支出 診療所数 C5401
# 0 北海道 0.88 0.43 0.04 -1.50 -0.49
# 1 青森県 -0.53 1.10 -1.36 -1.08 -0.61
# 2 岩手県 -0.54 1.03 0.11 -0.76 -0.451 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 36 37 38 39 | # ── クラスタリングの例で使うデータを用意します(47 都道府県)── import pandas as pd from sklearn.preprocessing import StandardScaler _df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1) _df = _df[_df['地域コード'].astype(str).str.match(r'^R\d{5}$', na=False)].copy() _df['年度'] = pd.to_numeric(_df['年度'], errors='coerce') _df = _df[_df['年度'] == _df['年度'].max()] _feats = ['総人口', '出生数', '死亡数', '消費支出(二人以上の世帯)'] for _c in _feats: _df[_c] = pd.to_numeric(_df[_c], errors='coerce') _df = _df.dropna(subset=_feats) X = _df[_feats].values X_std = StandardScaler().fit_transform(X) labels_index = _df['都道府県'].values 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.55266695 -0.52186218 -0.57999927 -1.23236363] [ 1.80241337 1.79067417 1.85344621 0.43471069] [-0.361482 -0.37327437 -0.36564101 0.48433324]] inertia: 49.7004245393956 シルエットスコア: 0.463
🎯 このコードでやること:クラスタリング — 教師なし学習による群構造発見に関連するステップ #2。基本統計量を計算します。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県
# 総人口・高齢化率・消費支出・診療所数(人口10万対)・標準地価 の5指標でクラスタリング
# 標準化後の X (shape=(47, 5)):
# pref A1101 高齢化率 消費支出 診療所数 C5401
# 0 北海道 0.88 0.43 0.04 -1.50 -0.49
# 1 青森県 -0.53 1.10 -1.36 -1.08 -0.61
# 2 岩手県 -0.54 1.03 0.11 -0.76 -0.451 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 | # ── クラスタリングの例で使うデータを用意します(47 都道府県)── import pandas as pd from sklearn.preprocessing import StandardScaler _df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1) _df = _df[_df['地域コード'].astype(str).str.match(r'^R\d{5}$', na=False)].copy() _df['年度'] = pd.to_numeric(_df['年度'], errors='coerce') _df = _df[_df['年度'] == _df['年度'].max()] _feats = ['総人口', '出生数', '死亡数', '消費支出(二人以上の世帯)'] for _c in _feats: _df[_c] = pd.to_numeric(_df[_c], errors='coerce') _df = _df.dropna(subset=_feats) X = _df[_feats].values X_std = StandardScaler().fit_transform(X) labels_index = _df['都道府県'].values 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') |
📤 このブロックは標準出力には何も出さない
🎯 このコードでやること:クラスタリング — 教師なし学習による群構造発見に関連するステップ #3。可視化(散布図/樹形図/時系列プロット)を描きます。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県
# 総人口・高齢化率・消費支出・診療所数(人口10万対)・標準地価 の5指標でクラスタリング
# 標準化後の X (shape=(47, 5)):
# pref A1101 高齢化率 消費支出 診療所数 C5401
# 0 北海道 0.88 0.43 0.04 -1.50 -0.49
# 1 青森県 -0.53 1.10 -1.36 -1.08 -0.61
# 2 岩手県 -0.54 1.03 0.11 -0.76 -0.451 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # ── クラスタリングの例で使うデータを用意します(47 都道府県)── import pandas as pd from sklearn.preprocessing import StandardScaler _df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1) _df = _df[_df['地域コード'].astype(str).str.match(r'^R\d{5}$', na=False)].copy() _df['年度'] = pd.to_numeric(_df['年度'], errors='coerce') _df = _df[_df['年度'] == _df['年度'].max()] _feats = ['総人口', '出生数', '死亡数', '消費支出(二人以上の世帯)'] for _c in _feats: _df[_c] = pd.to_numeric(_df[_c], errors='coerce') _df = _df.dropna(subset=_feats) X = _df[_feats].values X_std = StandardScaler().fit_transform(X) labels_index = _df['都道府県'].values from scipy.cluster.hierarchy import linkage, dendrogram Z = linkage(X_std, method='ward') plt.figure(figsize=(14, 6)) dendrogram(Z, labels=df['Prefecture'].values, leaf_rotation=90) plt.show() |
📤 このブロックは標準出力には何も出さない
🎯 このコードでやること:クラスタリング — 教師なし学習による群構造発見に関連するステップ #5。仮説検定・モデル評価を行います。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県
# 総人口・高齢化率・消費支出・診療所数(人口10万対)・標準地価 の5指標でクラスタリング
# 標準化後の X (shape=(47, 5)):
# pref A1101 高齢化率 消費支出 診療所数 C5401
# 0 北海道 0.88 0.43 0.04 -1.50 -0.49
# 1 青森県 -0.53 1.10 -1.36 -1.08 -0.61
# 2 岩手県 -0.54 1.03 0.11 -0.76 -0.451 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 36 37 38 39 40 | # ── クラスタリングの例で使うデータを用意します(47 都道府県)── import pandas as pd from sklearn.preprocessing import StandardScaler _df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1) _df = _df[_df['地域コード'].astype(str).str.match(r'^R\d{5}$', na=False)].copy() _df['年度'] = pd.to_numeric(_df['年度'], errors='coerce') _df = _df[_df['年度'] == _df['年度'].max()] _feats = ['総人口', '出生数', '死亡数', '消費支出(二人以上の世帯)'] for _c in _feats: _df[_c] = pd.to_numeric(_df[_c], errors='coerce') _df = _df.dropna(subset=_feats) X = _df[_feats].values X_std = StandardScaler().fit_transform(X) labels_index = _df['都道府県'].values from sklearn.cluster import KMeans, DBSCAN from sklearn.mixture import GaussianMixture from sklearn.metrics import silhouette_score, adjusted_rand_score # 複数手法の比較 results = {} for name, model in [ ('KMeans-k4', KMeans(n_clusters=4, random_state=42, n_init=10)), ('GMM-k4', GaussianMixture(n_components=4, random_state=42)), ('DBSCAN', DBSCAN(eps=1.2, min_samples=3)), ('Hierarchical', AgglomerativeClustering(n_clusters=4, linkage='ward')), ]: labels = model.fit_predict(X_std) # 標準化後のデータで比較する if len(set(labels)) > 1 and -1 not in labels: sil = silhouette_score(X_std, labels) results[name] = (labels, sil) print(f'{name:18} Silhouette = {sil:.3f}') # 手法間の一致度 km_lab = results['KMeans-k4'][0] for name in ['GMM-k4', 'Hierarchical']: if name in results: ari = adjusted_rand_score(km_lab, results[name][0]) print(f'KMeans vs {name}: ARI = {ari:.3f}') |
📤 実行例(実行時の標準出力) KMeans-k4 Silhouette = 0.469 GMM-k4 Silhouette = 0.378 Hierarchical Silhouette = 0.469 KMeans vs GMM-k4: ARI = 0.637 KMeans vs Hierarchical: ARI = 1.000
🎯 このコードでやること:クラスタリング — 教師なし学習による群構造発見に関連するステップ #6。結果を整形して表示します。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県
# 総人口・高齢化率・消費支出・診療所数(人口10万対)・標準地価 の5指標でクラスタリング
# 標準化後の X (shape=(47, 5)):
# pref A1101 高齢化率 消費支出 診療所数 C5401
# 0 北海道 0.88 0.43 0.04 -1.50 -0.49
# 1 青森県 -0.53 1.10 -1.36 -1.08 -0.61
# 2 岩手県 -0.54 1.03 0.11 -0.76 -0.451 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 | # ── クラスタリングの例で使うデータを用意します(47 都道府県)── import pandas as pd from sklearn.preprocessing import StandardScaler _df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1) _df = _df[_df['地域コード'].astype(str).str.match(r'^R\d{5}$', na=False)].copy() _df['年度'] = pd.to_numeric(_df['年度'], errors='coerce') _df = _df[_df['年度'] == _df['年度'].max()] _feats = ['総人口', '出生数', '死亡数', '消費支出(二人以上の世帯)'] for _c in _feats: _df[_c] = pd.to_numeric(_df[_c], errors='coerce') _df = _df.dropna(subset=_feats) X = _df[_feats].values X_std = StandardScaler().fit_transform(X) labels_index = _df['都道府県'].values from scipy.cluster.hierarchy import linkage, dendrogram, fcluster from scipy.spatial.distance import pdist import matplotlib.pyplot as plt # 階層クラスタリング + デンドログラム Z = linkage(X, method='ward') fig, ax = plt.subplots(figsize=(14, 5)) dendrogram(Z, labels=df['Prefecture'].values, leaf_rotation=90, ax=ax) ax.axhline(y=6.5, color='r', linestyle='--', label='切り捨て位置 (k=4)') ax.legend(); plt.tight_layout() plt.savefig('dendrogram.png', dpi=110) # 階層から flat なクラスタを取り出す labels_hier = fcluster(Z, t=4, criterion='maxclust') print('階層クラスタリング結果:', np.bincount(labels_hier)) |
📤 実行例(実行時の標準出力) 階層クラスタリング結果: [ 0 21 16 9 1]
🎯 このコードでやること:クラスタリング — 教師なし学習による群構造発見に関連するステップ #7。47都道府県データに当てはめて確認します。
📥 入力例(df.head())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023] # 2023年度の47都道府県
# 総人口・高齢化率・消費支出・診療所数(人口10万対)・標準地価 の5指標でクラスタリング
# 標準化後の X (shape=(47, 5)):
# pref A1101 高齢化率 消費支出 診療所数 C5401
# 0 北海道 0.88 0.43 0.04 -1.50 -0.49
# 1 青森県 -0.53 1.10 -1.36 -1.08 -0.61
# 2 岩手県 -0.54 1.03 0.11 -0.76 -0.451 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import optuna from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score # クラスタ数 + アルゴリズムを最適化 def objective(trial): algo = trial.suggest_categorical('algo', ['kmeans', 'ward', 'gmm']) k = trial.suggest_int('k', 2, 8) if algo == 'kmeans': m = KMeans(n_clusters=k, random_state=42, n_init=10) elif algo == 'ward': m = AgglomerativeClustering(n_clusters=k, linkage='ward') else: m = GaussianMixture(n_components=k, random_state=42) labels = m.fit_predict(X) if len(set(labels)) > 1: return -silhouette_score(X, labels) return 0 study = optuna.create_study(direction='minimize') study.optimize(objective, n_trials=30) print('Best:', study.best_params, ' Silhouette:', -study.best_value) |
📤 実行例(実測)
Best: {'algo': 'gmm', 'k': 2} Silhouette: 0.7914643636382689| ライブラリ / 関数 | 用途 |
|---|---|
sklearn.cluster.KMeans | 最も標準的 |
sklearn.cluster.AgglomerativeClustering | 階層クラスタリング |
sklearn.cluster.DBSCAN | 密度ベース |
scipy.cluster.hierarchy | デンドログラム描画 |
hdbscan | 階層 DBSCAN |
yellowbrick.cluster | シルエット可視化 |
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]) |
クラスタリング(clustering)は、 ラベルなしのデータを類似度に基づいて自動的にグループ分けする教師なし学習の一種。 「47都道府県を、 家計の似た傾向でグループ化」のような問題。
「k個に分ける」とあらかじめ決めて最適化。 代表:k-means、 k-medoids、 ファジー C-means。 計算は高速。
近いペアから順にまとめていく(凝集型)、 または大きく分割(分割型)。 結果がデンドログラムに。 任意の数のクラスタが取れる。 代表:Ward法、 群平均法。
「密度が高い領域がクラスタ」と考える。 代表:DBSCAN、 HDBSCAN、 OPTICS。 任意の形状を捉え、 ノイズ判別もできる。
| 距離 | 公式 | 使い時 |
|---|---|---|
| ユークリッド距離 | √Σ(xᵢ-yᵢ)² | 標準。 連続値 |
| マンハッタン距離 | Σ|xᵢ-yᵢ| | 高次元、 ロバスト |
| マハラノビス距離 | √((x-μ)ᵀΣ⁻¹(x-μ)) | 変数の相関を考慮 |
| コサイン距離 | 1 - cos(x, y) | テキスト、 ベクトル空間 |
| Jaccard 距離 | 1 - |X∩Y|/|X∪Y| | 集合データ |
図の読み方:左(エルボー法)は k を増やすほど inertia が単調に減少するので、 「下がり方が急に緩くなる折れ目」(この図では k=3〜4 付近)を探す。 右(シルエット係数)は最大となる k を探すが、 この図のように最大が k=6 になるなど、 指標間で最適 k が割れることもある。 その場合は 1 つの指標を鵜呑みにせず、 解釈のしやすさ・事前知識も併せて総合的に決める。
クラスタ内分散の合計(inertia)を k に対してプロット。 折れ目(elbow)が最適 k。
各点が自クラスタ内でどれだけ凝集し、 他クラスタからどれだけ離れているかを測る。 1に近いほど良い。
ランダムデータと比較して「実データの方がクラスタ構造が強い」かを定量化。
業務的に「3地区に分けたい」「5セグメントが必要」と決まっている場合は、 それを優先する。
クラスタリング を 47 都道府県 × 複数列 で k-means に適用する際に踏みやすい落とし穴を 5 件挙げます。 47 都道府県という小標本(n=47)に固有の問題が多いため、 先に頭に入れておきましょう。
クラスタリングを一言で言えば 「正解ラベルを一切与えず、 似たサンプル同士を自動でグループにまとめる教師なし学習」。 分類(教師あり)が「先生が付けた正解に合わせる」のに対し、 クラスタリングは「データの内部構造をアルゴリズムが自力で発見する」点が本質的に違います。 だからこそ正解がなく、 評価が難しいという宿命を最初から背負います。
手法は「何をもって近い/似ているとするか」で大きく3系統に分かれます。
比喩でいえば、 k-means は「4つの磁石(重心)を置いて鉄粉を引き寄せる」、 階層型は「近いもの同士を手をつながせて家系図を作る」、 DBSCAN は「人が混み合っている場所を1つの群衆とみなし、 ぽつんと立つ人は無視」というイメージ。 同じデータでも、 使う手法・距離・変数が変われば別のグループ分けが出る——「唯一の正しい分類」ではなく「分析者の選択を映した類型化」だ、 というのがクラスタリングを扱う際の最も大切な直感です。
本文の落とし穴リストを、 SSDSE-B-2026(2023年・47都道府県)の実測値で「本当にそうなるのか」検証します。 変数は本文と同じ5指標(総人口 A1101・高齢化率・消費支出・人口10万対診療所数・標準地価 C5401)。 数値はすべて実行結果で、 合成データではありません。
標準化ありとなしで k-means(k=4)を実行し、 シルエット係数とクラスタサイズを比べます。
| 前処理 | シルエット | クラスタサイズ | 実態 |
|---|---|---|---|
| 標準化あり | 0.268 | [13, 1, 8, 25] | 5変数がほぼ平等に効く |
| 標準化なし(生値) | 0.735 | [5, 37, 1, 4] | 37県が一塊。 実質「総人口・標準地価」だけで分割 |
ここが罠です。 標準化を忘れた方がシルエットは 0.735 と一見「高品質」に見える。 しかし中身は、 桁の大きい総人口(数百万)と標準地価(数万円)だけで距離が決まり、 高齢化率(20〜35%)や消費支出はほぼ無視され、 37県が1つの塊に潰れた退化した分割にすぎません。 教訓は2つ——(1) 単位の違う変数は必ず 標準化 する、 (2) シルエットが高い=良いクラスタリング、 とは限らない(指標は「分かれ具合」を測るだけで「意味のある分かれ方か」は測らない)。
構造を持たない乱数データ($N(0,1)$ の 47×5 行列、 架空データ)を k-means(k=4)で20回クラスタリングした平均シルエットは 0.185(範囲 0.151〜0.229)。 つまりクラスタ構造がゼロでも 0.18 程度は当然出る。 一方、 実データ(47都道府県)の k=4 シルエットは 0.268 で、 乱数ベースラインをわずかに上回る程度。 これは「47県の5指標には強いクラスタ構造は存在せず、 連続的なグラデーションを便宜的に4分割している」ことを示します。 「クラスタが出た=構造がある」ではない好例で、 乱数データとのギャップ(ギャップ統計量の発想)で確かめるのが定石です。
標準化後 k-means の $k=2\sim6$ を3指標で評価すると、 最適 $k$ が指標ごとに食い違います(シルエット・CHは大きいほど良い、 Davies-Bouldinは小さいほど良い)。
| k | Inertia | シルエット | Davies-Bouldin | Calinski-Harabasz |
|---|---|---|---|---|
| 2 | 153.3 | 0.488 | 0.958 | 24.0 |
| 3 | 119.5 | 0.248 | 1.154 | 21.3 |
| 4 | 89.1 | 0.268 | 0.969 | 23.5 |
| 5 | 74.3 | 0.272 | 0.942 | 22.7 |
| 6 | 65.4 | 0.203 | 1.030 | 21.3 |
シルエットと Calinski-Harabasz は $k=2$(都市/地方の二分)を最良とし、 Davies-Bouldin は $k=5$ を最良とする。 エルボー(Inertia)は $k=3\sim4$ で緩む。 単一指標を鵜呑みにすると結論が変わるため、 複数指標+解釈しやすさ+事前理論で総合判断するしかありません(本文が $k=4$ を採るのは解釈性重視の実務判断)。
同じ標準化データ(k=4)で手法を替え、 k-means を基準に一致度(ARI: 調整ランド指数、 1が完全一致)を測りました。
| 手法 | シルエット | k-means とのARI |
|---|---|---|
| k-means | 0.469 | — |
| 階層・完全連結 | 0.469 | 1.000 |
| 階層・Ward法 | 0.469 | 1.000 |
| GMM(混合ガウス) | 0.378 | 0.637 |
分割型(k-means)と階層型(完全連結・Ward 法)は ARI = 1.000、 つまり 47 県すべてでまったく同じ 4 分割になりました。 GMM だけは ARI 0.637・シルエット 0.378 とやや乖離します。 GMM は楕円形のクラスタと確率的な所属を許すため、 球状を仮定する k-means とは別の切り方をしたわけです。 複数手法で安定して同じ群が出るかを確認するのが頑健性チェックで、 ここでは「k-means と階層法は信頼できるが、 GMM 解は別途吟味が要る」と読めます。
DBSCAN(min_samples=3)の近傍半径 $\varepsilon$ を動かすと、 検出クラスタ数とノイズ点数が大きく振れます。
| ε | 検出クラスタ数 | ノイズ点数(/47) |
|---|---|---|
| 1.0 | 1 | 17 |
| 1.2 | 1 | 15 |
| 1.5 | 2 | 5 |
| 2.0 | 1 | 2 |
$\varepsilon$ を少し変えるだけで「17県がノイズ」から「全県ほぼ1塊」まで結果が一変します。 5次元・47点という疎で小さいデータでは密度差が乏しく DBSCAN が素直に効かないことも分かります。 $\varepsilon$ は勘で決めず、 k距離プロット(k-distance plot)や、 $\varepsilon$ 不要の HDBSCAN を検討するのが定石です。
クラスタリングは「手法・評価・クラスタ数決定・前処理」の4層で整理すると全体像が掴めます。 各項目は本サイトの個別ページ(存在するもののみリンク)へ接続します。
| 手法 | 系統 | 強み | 弱み・仮定 |
|---|---|---|---|
| k-means | 分割・重心 | 高速・大規模向き | k指定必須、 球状仮定、 初期値依存 |
| 階層(Ward等) | 連結 | k後決め、 樹形図で構造可視化 | 計算量 $O(n^3)$、 中規模まで |
| DBSCAN/HDBSCAN | 密度 | 非球形・ノイズ検出、 k自動 | ε・MinPts敏感、 密度差に弱い |
| GMM | モデル(確率) | 楕円形・ソフト所属・重なり許容 | 正規分布仮定、 EMが局所解 |
| スペクトラル | グラフ | 複雑な非線形構造に強い | 類似度行列の構築が要、 大規模で重い |
📝 リンク方針:本補足のリンクは html/glossary/ 内に実在するページのみに張っています。 シルエット係数・エルボー法・ギャップ統計量は独立ページが未整備のため、 用語のみをテキストで示しています(今後ページが追加されればリンク化予定)。
クラスタリング がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。
🌐 統計・データサイエンス › 教師なし学習 › クラスタリング › クラスタリング
中心に クラスタリング を置き、 そこから PCA・因子分析・標準化・共分散・k-means・階層型 など 計 11 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語とあとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。
大きな円が小さな円を包含する Circle Packing 図。 「クラスタリング」は緑色でハイライト。
長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「クラスタリング」は緑色でハイライト。
| マップ | 分かること | こんな時に見る |
|---|---|---|
| 🔗 関係マップ | 手法間の横の関係(前提→発展→応用) | 「次に何を学べばよい?」 学習順序の判断 |
| ⭕ 包含マップ | 分類体系の入れ子構造(上位⊃下位) | 「この手法はどんなジャンルに属する?」 |
| 🌳 ツリーマップ | 分野の規模比較(面積=ボリューム) | 「データサイエンス全体の俯瞰像」 |
💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは クラスタリング の隣に何が並ぶかを、 包含マップとツリーマップは 統計・データサイエンス → クラスタリング → クラスタリング という入れ子の位置を示します。 「クラスタリングには他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。
「クラスタリング」は教師なしでデータを群に分ける手法で、 上流の標準化と下流の評価指標 (シルエット・エルボー) を欠くと、 クラスタ数の主観で結論が変わってしまう。
上流の標準化と次元削減で距離を整え、 並列の k-means・階層型・DBSCAN を結果比較し、 下流のシルエット係数とプロット可視化を組み合わせれば、 SSDSE 都道府県を堅牢にライフスタイル群に分けられる。
クラスタリング手法は「クラスタ数 k を事前に決められるか」「クラスタ形状は球形か」「ノイズ点を分離したいか」「所属確率が欲しいか」「データ規模はどれくらいか」の 5 つで選び分ける。 以下に判断フローと典型シナリオを示す。
| 問い | Yes なら | No なら |
|---|---|---|
| クラスタ数 k を事前に決められるか | k-means / k-medoids / GMM | DBSCAN / HDBSCAN / 階層型 |
| クラスタ形状は球形か (等方分散) | k-means / GMM | DBSCAN / OPTICS / Mean Shift |
| 階層構造 (デンドログラム) を見たいか | Ward / 単連結 / 完全連結 / 群平均 | 分割型 / 密度ベースへ |
| ノイズ点を「どこにも属さない」と判定したいか | DBSCAN / HDBSCAN | k-means など (全点を必ず割当) |
| 所属確率 (重なり) が欲しいか | GMM (EM アルゴリズム) / Fuzzy c-means | k-means など (硬い割当) |
| 大規模データ (n > 10 万) か | MiniBatchKMeans / BIRCH | 標準実装でよい |
sklearn.cluster.KMeans(n_clusters=4)scipy.cluster.hierarchy.linkage(method='ward') + dendrogramsklearn.cluster.DBSCAN(eps=0.5, min_samples=5)sklearn.mixture.GaussianMixture(n_components=k)MiniBatchKMeans または事前に PCA で次元削減HDBSCAN や OPTICS で密度ベースに任せるStandardScaler で z-score 化 (これを忘れると距離が桁の大きい変数で支配される)n_init=10 以上で複数初期値、 結果が安定するか確認クラスタリングの本質は「手法ごとに『クラスタとは何か』の定義(前提)が違う」こと。 下のキャンバスに 2 次元データを用意し(プリセット選択、 またはクリック / タップで点を追加)、 k-means・階層型(Ward / 単連結)・密度ベース(DBSCAN)がそれぞれ同じデータをどうグループ分けするかを、 その場で見比べられます。 計算はすべてブラウザ内で正確に実行(k-means は k-means++ 初期化 × 10 リスタートの最良解、 階層型は凝集型の全ペア距離計算、 DBSCAN は標準アルゴリズム)。 平均シルエット係数とクラスタ内二乗和(WSS)もリアルタイムで更新されます。
キャンバスをクリック / タップすると点を追加できます(最大 300 点)。 大きい × は k-means の重心。 灰色の × は DBSCAN が「どのクラスタにも属さない」と判定したノイズ点(シルエット係数・WSS の計算から除外)。 座標は [0, 1] × [0, 1] に正規化済み。