主成分分析 (PCA) は多変数データを分散最大の軸 (主成分) に射影して次元削減する手法で、 共分散行列の固有値分解 Σ = VΛV⊤ がその数学的本体である。 SSDSE-B-2026 の 6 列 (総人口・65歳以上人口・出生数・婚姻件数・一般診療所数・消費支出) を 2 主成分に圧縮し、 PC1=「人口規模軸」・PC2=「消費水準軸」と解釈する。
これらのキーワードは「pca の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。
🍰 まずはやさしく
たくさんの情報をまとめる魔法のような道具です。
少ない項目でデータの特徴を掴むために使います。
テストの多くの点数をまとめて「勉強量」とする例です。
この章では情報をまとめる仕組みを学びます。
sklearn.decomposition.PCA(n_components=2)あなたが47都道府県について、 「人口」「年齢構成」「所得」「失業率」「医療費」「教育水準」「気温」など10個の指標を持っているとします。 「どの県とどの県が似ているか」「全体としてどんなパターンがあるか」を知りたい。 でも10次元の空間は脳で想像できません。 10次元を2次元に圧縮して可視化したい──これが PCA(主成分分析)の出番です。
PCA の核心アイデア: データのばらつき(=情報量)が最も大きい方向に新しい軸(第1主成分)を立て、 次にそれと直交する中でばらつきが最大の方向に第2主成分を立て...と続けます。 元の10個の変数の代わりに、 最初の数本の主成分だけを使えば、 ほとんどの情報を保ちながら次元を減らせます。
例えば SSDSE の社会経済指標を PCA すると、 第1主成分は「都市↔︎地方」軸(東京・神奈川 vs 秋田・島根)、 第2主成分は「世帯の消費水準」軸など、 解釈可能な軸として現れることがあります。 これにより 6次元のデータを 2次元の散布図で「都道府県マップ」として描けるのです。
注意:PCA は「事前に標準化(平均0・分散1)が必須」です。 単位や桁が違う変数(人口 vs 失業率)をそのまま入れると、 桁が大きい変数だけで第1主成分が決まってしまいます。
🍰 まずはやさしく
データのまとめ方について書かれた部分です。
複雑なデータを分かりやすく整理するために使います。
都道府県のたくさんの指標をまとめる例で考えます。
ここでは分析の手順と使い道を詳しく読みます。
論文で「主成分分析(PCA)」「第1主成分」「分散説明率」と書かれている部分。 多くの社会経済データのまとめ・可視化に登場。
主成分分析(PCA) とは:多次元データを「分散が最大となる軸(主成分)」へ射影して次元削減。可視化や前処理に多用。
本ページは PCA を、 SSDSE-B-2026 47 都道府県 × 6 指標の標準化済みデータに対して実演する。 共分散行列 Σ の固有値分解→分散説明率→ローディング解釈→バイプロットまでを numpy と sklearn.decomposition.PCA で対応付け、 第 1・第 2 主成分で全分散の 80% 以上を説明できることを示す。
「pca」は統計・データサイエンスの体系における重要概念のひとつ。 本ページは「定義・直感・数式・実装・落とし穴・関連手法」の 6 視点で構成され、 各視点は独立して読めるが順序通り読むと体系的な理解が得られる。
🍰 まずはやさしく
データの形を別の角度から見るイメージです。
似ているグループがあるかを見つけるために使います。
スマホの画面で写真の構図を決める感覚に似ています。
ここでは図を使って直感的に仕組みを読みます。

図の左上、 右下、 などにグループが見えるはずです。 これは元の6次元では分かりにくかった「都道府県の特徴の似ている度合い」を、 たった2次元で表現できているということ。 PCA がうまく機能している証拠です。
具体的に PCA が何をしているか:
ローディング(loading):各主成分が元のどの変数と強く関係しているかを示す係数。 ローディングを見れば「第1主成分は人口や診療所数が強く効いている → 人口規模軸」のような解釈ができます。
主成分得点の散布図に、 元変数の loading を矢印で重ね合わせたのがバイプロット。 「各サンプルがどの変数の影響で配置されているか」が一目で分かる強力な可視化。
累積寄与率が80%(または90%)を超える数の主成分を採用。 もっとも一般的。
固有値が1以上の主成分を採用(標準化データの場合)。 「平均的な変数より分散が大きい主成分」を残す考え方。
スクリープロットで「カーブが急に折れる点」を探す。 視覚的判断だが直感的。
ランダムデータの固有値分布と比較。 ランダムを超える主成分を採用。 統計的根拠あり。
高次元データで多重共線性を解消、 計算量削減。 ただし PCA は分散最大化であり、 教師あり学習の予測精度を最大化はしません。
クラスタリング結果を 2D で見るための定番。 t-SNE や UMAP の代替・併用。
画像処理:固有顔(eigenfaces)で顔画像認識の前処理。 ファイルサイズ削減(JPEG の DCT に類似)。
主要な主成分で再構成した結果と元データの残差が大きいサンプルを異常と判定。
PCA で共分散行列を単位行列に変換する前処理。 PCA + 標準化のような効果で学習を加速。
主成分分析の核心は「データのばらつき(分散)が最大になる方向を探すこと」です。 言葉だけでは掴みにくいので、 下の散布図を実際に触って確かめましょう。 点をドラッグして雲の形を変えたり、 プリセットを切り替えたりすると、 第1主成分(PC1)と 第2主成分(PC2)の軸がその場で再計算され、 寄与率のバーも動きます。 すべての計算(2×2 共分散行列の固有値・固有ベクトルの解析解)はブラウザ内で毎フレーム実行されており、 外部ライブラリは一切使っていません。
共分散行列を $\Sigma=\begin{pmatrix}a & b\\ b & d\end{pmatrix}$ とすると、 固有値は判別式付きの 2 次方程式で解析的に求まります(このページの JS はこの式をそのまま実装)。
任意方向 $\theta$(単位ベクトル $\mathbf{w}=(\cos\theta,\sin\theta)$)の分散は $\mathrm{Var}=a\cos^2\theta + 2b\cos\theta\sin\theta + d\sin^2\theta$ で計算できます。 スライダーの下のバーはこの値を毎フレーム評価しており、 その最大値がちょうど $\lambda_1$(PC1)になります。
おもちゃの散布図ではなく、 実際の SSDSE-B-2026(cp932 / skiprows=[1] / 2023 年・47 都道府県)で、 キーワード索引と同じ 6 指標(総人口・65歳以上人口・出生数・婚姻件数・一般診療所数・消費支出)を標準化して PCA を計算すると、 次の実測値が得られます。
| 主成分 | 固有値 λ | 寄与率 | 累積 | 意味づけ(ローディング) |
|---|---|---|---|---|
| PC1 | 5.04 | 84.0% | 84.0% | 人口規模軸(総人口・出生数・婚姻件数・65歳以上人口・一般診療所数が各 |0.44| 前後で均等に効く) |
| PC2 | 0.879 | 14.6% | 98.6% | 消費水準軸(消費支出のローディングが +0.98 と突出) |
| PC3 | 0.063 | 1.0% | 99.7% | ほぼノイズ |
6 次元がたった 2 本で全分散の 98.6%を説明できます(人口系 5 指標が互いに強く相関しているため)。 PC1 得点の両端は 東京都(−9.8)・大阪府(−5.0)・神奈川県(−5.0)(大規模側)と 鳥取県(+1.8)・福井県(+1.6)・和歌山県(+1.6)(小規模側)。 PC2 得点の上位は三重県・富山県・埼玉県(消費が高い側)で、 まさに「人口規模」と「消費水準」という解釈可能な 2 軸に分解されています。 ※固有ベクトルの符号は数学的に任意なので、 符号の向き自体には意味はありません。
🍰 まずはやさしく
計算ルールを決めた数式のページです。
正確にデータをまとめるための基準を作るために使います。
部活の成績を点数で計算して順位をつける例です。
ここでは計算式と記号の意味について読みます。
$$ z_{ij} = \sum_{k=1}^{p} v_{kj} \cdot x_{ik} $$
i番目のサンプルの j番目主成分得点 = 元の変数 × 固有ベクトルの重み付き和。
$$ \text{寄与率}_j = \frac{\lambda_j}{\sum_{k=1}^{p} \lambda_k} $$
各主成分が全分散のうち何%を説明するか。 固有値の比。
第1〜j主成分までの寄与率の合計。 通常80%や90%を超える主成分まで採用。
| 記号 | 読み方 | 意味 |
|---|---|---|
| X | エックス | n×p のデータ行列 |
| Σ | シグマ(大文字) | 共分散行列(p×p) |
| V | ブイ | 固有ベクトル(主成分方向) |
| λ_j | ラムダ サブ ジェイ | j番目主成分の固有値(=分散) |
| Z | ゼット | 主成分得点行列 |
主成分分析(PCA)を実務で正しく使うために必須となる 4 つの追加トピックを、 SSDSE-B-2026 で実証しながら整理します。 「標準化の有無」 → 「寄与率の読み方」 → 「主成分の意味づけ」 → 「ローディングの可視化」の流れで進めます。
SSDSE-B-2026 のように単位の異なる変数(総人口は数百万、 合計特殊出生率は 1 前後)を混ぜると、 標準化しない PCAは単に「数値の大きい変数」が支配的になります。 必ず z-score 標準化を行ってから PCA を計算してください。
|
主成分の寄与率は 各主成分が説明する分散の割合です。 累積寄与率 70-80% を超えるところで打ち切るのが定石ですが、 SSDSE-B-2026 のような 強く相関した都道府県データでは、 第 1 主成分だけで 50% を超えることも珍しくありません。 その場合は第 1 主成分の解釈に注力するのが効率的です。
| 基準 | 解釈 |
|---|---|
| 累積寄与率 70%+ | 主要構造を捉えた |
| Kaiser 基準 | 固有値 ≥ 1 の成分を採用 |
| スクリー基準 | 折れ線の「肘」を見る |
| 並行分析 | 乱数固有値との比較 |
主成分は元変数の線形結合です。 ローディング行列を見て、 「どの元変数が大きく寄与しているか」で 意味づけします。 SSDSE-B-2026 では、 第 1 主成分が「総人口・生産年齢人口・婚姻件数」など 人口規模を表すケースが典型的です。
|
バイプロットは、 都道府県(サンプル)を点で、 変数(次元)を矢印で同じ図に配置する PCA の可視化テクニックです。 都道府県のクラスタと、 各クラスタが「どの変数で特徴づけられているか」を一望できます。
PCA は次元削減のためだけでなく、 変数構造の発見にも極めて有効です。 SSDSE-B-2026 で PCA を計算したら、 必ず累積寄与率・ローディング表・バイプロットの 3 点セットを提出資料に含めるようにしましょう。 これだけで「都道府県データの全体構造が分かっている」ことを示せます。
PCA は本質的に 特異値分解 (SVD) の応用です。 中心化された行列 X に対し $X = U S V^\top$ と分解したとき($S$ は特異値の対角行列。 共分散行列 $\Sigma$ と混同しないよう $S$ と書く)、 $V$ の列ベクトルが主成分方向、 $S^2 / (n-1)$ が固有値(=各主成分の分散)に対応します。 この視点は、 「共分散行列を作らずに直接 X から PCA を計算できる」ことを意味し、 高次元データで数値安定性が高い実装の根拠となります。
|
説明変数間に強い相関(多重共線性)がある場合、 OLS は不安定になります。 そこで 主成分回帰では、 PCA で得た上位 k 主成分を新たな説明変数として使います。 SSDSE-B-2026 で 100 を超える数値特徴量から「合計特殊出生率 (A4103)」を予測する場面では、 PCR が安定推定に役立ちます。
|
コンペや論文で PCA を使うときは、 以下の 5 つの図表をセットで提出すると説得力が増します。
これらをそろえれば、 「変数構造の理解」「外れ値の発見」「次元削減」「可視化」「予測前処理」の 5 目的すべてで PCA が機能していることを示せます。 SSDSE-B-2026 を題材にこのテンプレートを身につけておくと、 他のデータでも即座に同じ手順を再現できる強い武器になります。
| 手法 | 線形/非線形 | 教師あり/なし | 向き |
|---|---|---|---|
| PCA | 線形 | なし | 分散保存 |
| Kernel PCA | 非線形 | なし | 非線形多様体 |
| t-SNE | 非線形 | なし | 局所構造可視化 |
| UMAP | 非線形 | なし | 高速・大域構造保存 |
| LDA | 線形 | あり | クラス分離 |
| オートエンコーダ | 非線形 | なし | 深層学習・大規模 |
PCA が「分散最大化の線形投影」なら、 t-SNE/UMAP は「局所近傍の保存」、 オートエンコーダは「再構成誤差最小化」と、 それぞれ最適化対象が異なります。 SSDSE-B-2026 のような 少数サンプル・量的データには PCA が第一選択ですが、 サンプル数が増え、 非線形構造が疑われる場合には UMAP や Kernel PCA を併用するのが現代的なベストプラクティスです。
fit_transform で学習し、 新規データは transform のみで投影する(再フィット禁止)。PCA は 1901 年に Pearson が、 1933 年に Hotelling が独立に定式化した古典手法ですが、 100 年以上経った今もデータ解析の 第一線の道具として君臨し続けています。 「次元削減と聞いたらまず PCA」、 「変数が多いと感じたらまず PCA」を合言葉に、 自分のデータ解析プロセスに必ず組み込みましょう。 SSDSE-B-2026 のような身近な公的データで何度も練習することで、 「結果を見て即座に解釈する」能力が育ちます。
以下の練習問題に「自分の言葉で」答えられるかを確認しよう。 詰まったら対応する節へ戻ること。
🛠 自分で手を動かす(5 分課題):
StandardScaler で標準化。sklearn.decomposition.PCA でフィットし、 explained_variance_ratio_ をプロット (スクリープロット)。components_(負荷量)の上位 3 変数で各主成分の意味を解釈し、 1 行で命名する(例: PC1=「都市規模」、 PC2=「高齢化度」)。PCA は「標準化 → 共分散行列 → 固有値分解 → 射影」の 4 ステップだが、 各ステップでつまずきやすい。 SSDSE-B-2026 を使って 4 つの角度から確認する。
このコードでやること: SSDSE-B-2026 で「総人口」「一般診療所数」「合計特殊出生率」を選び、 標準化あり/なしで PCA を実行する。 標準化なしでは「総人口」が支配的になることを示す。
📥 入力: SSDSE-B-2026.csv、 47都道府県、 数値 3 列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import pandas as pd from sklearn.decomposition import PCA 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'] == 2023].drop(columns=['SSDSE-B-2026']) # 2023年度・47都道府県 cols = ['A1101', 'I5102', 'A4103'] # 総人口 / 一般診療所数 / 合計特殊出生率 X = df[cols].fillna(df[cols].mean()).values # 標準化なし pca_raw = PCA(n_components=3).fit(X) print('標準化なし: 寄与率 =', pca_raw.explained_variance_ratio_.round(3)) print(' PC1 の各変数への重み =', pca_raw.components_[0].round(3)) # 標準化あり Xs = StandardScaler().fit_transform(X) pca_std = PCA(n_components=3).fit(Xs) print('標準化あり: 寄与率 =', pca_std.explained_variance_ratio_.round(3)) print(' PC1 の各変数への重み =', pca_std.components_[0].round(3)) |
📤 実行例:
💬 結果の読み方: 標準化なしでは PC1 が「総人口」そのもの(寄与率 100%)になり、 他の情報は捨てられる。 標準化後は総人口と一般診療所数がほぼ同じ重み(0.62 前後)で PC1 を構成し、 合計特殊出生率は符号が逆(-0.48)で効く。 単位の異なる変数は必ず標準化。
このコードでやること: 6 変数を使った PCA で寄与率と累積寄与率を計算、 80% 規則と肘ルールでの主成分数を確認する。
📥 入力: SSDSE-B-2026 の総人口、 65歳以上人口、 出生数、 婚姻件数、 一般診療所数、 消費支出の 6 列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import numpy as np import pandas as pd from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler cols = ['A1101','A1303','A4101','A9101','I5102','L3221'] df_sub = df[cols].fillna(df[cols].mean()) Xs = StandardScaler().fit_transform(df_sub.values) pca = PCA().fit(Xs) ratio = pca.explained_variance_ratio_ cum = ratio.cumsum() for i, (r, c) in enumerate(zip(ratio, cum), 1): print(f'PC{i}: 寄与率={r:.3f} 累積={c:.3f}') print() print('80% 規則: 累積 80% を超える最小の主成分数 =', int(np.argmax(cum >= 0.8)) + 1) |
📤 実行例:
💬 結果の読み方: 人口規模系の 5 変数が強く相関しているため、 PC1 だけで 84.0% を説明し 80% 規則なら 1 主成分で足りる。 PC1+PC2 なら 98.6% → 「6 次元のデータを 2 次元の散布図にしてもほとんど情報が失われない」ことを意味する。 可視化は PC1×PC2 の 2D で十分。
このコードでやること: ②の結果から PC1 と PC2 のローディング(各変数の重み)を計算し、 軸の意味を言語化する。
📥 入力: ②の pca オブジェクト、 df_sub。
1 2 3 4 5 6 7 8 9 10 11 | import pandas as pd loadings = pd.DataFrame( pca.components_[:2].T, columns=['PC1','PC2'], index=['総人口','高齢者','出生数','婚姻','診療所','消費支出'] ).round(3) print(loadings) print() print('PC1 で絶対値最大:', loadings['PC1'].abs().idxmax()) print('PC2 で絶対値最大:', loadings['PC2'].abs().idxmax()) |
📤 実行例:
💬 結果の読み方: PC1 は「総人口、 高齢者、 出生数、 婚姻、 診療所」がすべて 0.44 前後で同じ向き → 「人口規模軸」と命名できる。 PC2 は消費支出(二人以上の世帯当たり)だけ 0.99 と突出 → 「世帯消費水準軸」と解釈。 主成分の意味づけはローディングを必ず確認。
このコードでやること: 2 主成分から元の 6 次元に逆変換し、 各都道府県でどれだけ復元できるか RMSE で測る。
📥 入力: ②の Xs(標準化済データ)。
1 2 3 4 5 6 7 8 9 | import numpy as np from sklearn.decomposition import PCA for k in [1, 2, 3, 4]: pca_k = PCA(n_components=k).fit(Xs) X_proj = pca_k.transform(Xs) X_recovered = pca_k.inverse_transform(X_proj) rmse = np.sqrt(((Xs - X_recovered)**2).mean()) print(f'PC1〜PC{k} で復元: RMSE={rmse:.4f}') |
📤 実行例:
💬 結果の読み方: PC1 だけでは標準偏差 0.40 程度のずれ、 PC2 まで使うと 0.12 まで縮む。 累積寄与率 98.6% に対応する誤差。 「2 次元プロットで OK」なのは、 この程度の精度損失を許容できる場面に限る。
2変数(高齢化率 x、 死亡率 y、 標準化済)で PCA の動きを直感的に追ってみましょう。
PCA vs 因子分析(FA):似ているが目的が違います。 PCA は「観測変数の全分散をなるべく少ない軸で説明」、 FA は「観測変数の共通分散のみを共通因子で説明(独自分散は誤差扱い)」。 因子分析の方が「潜在変数の存在」という仮説に踏み込むので、 心理学・社会学のスケール開発で好まれます。
PCA vs SVD(特異値分解):数学的にはほぼ同じ。 SVD はより一般的な行列分解法で、 PCA は SVD の特殊例。 NumPy の np.linalg.svd でも PCA を実装できます。
PCA の限界:
PCR (Principal Component Regression):多重共線性で OLS が不安定なとき、 説明変数を PCA してから上位主成分だけで回帰する手法。 解釈は犠牲になるが安定性が向上。
47都道府県の家計5項目(食料費、 住居費、 教育費、 光熱費、 保健医療費)で PCA を実施した結果:
| 主成分 | 固有値 | 寄与率 | 累積寄与率 |
|---|---|---|---|
| PC1 | 2.310 | 45.2% | 45.2% |
| PC2 | 1.197 | 23.4% | 68.6% |
| PC3 | 0.900 | 17.6% | 86.3% |
| PC4 | 0.472 | 9.2% | 95.5% |
| PC5 | 0.231 | 4.5% | 100.0% |
PC1だけで全分散の 45.2% を説明。 PC1とPC2で68.6%、 PC3まで含めると86.3%。 累積寄与率80%規則なら「主成分3つ」、 カイザー基準(固有値≥1 は PC1〜PC2)なら「主成分2つ」が目安で、 基準によって結論が分かれる好例。 可視化目的なら PC1×PC2(68.6%)でも大まかな構造は掴める。 累積寄与率は必ず単調増加し、 全主成分を使えば 100% になる点も表で確認しよう。
主成分は合成変数。 元の変数の重み付き和です。 重み(loading)を見ることで主成分の「意味」が分かります。
| 変数 | PC1の重み | PC2の重み |
|---|---|---|
| 食料費 | +0.593 | +0.047 |
| 住居費 | -0.063 | -0.667 |
| 教育費 | +0.588 | -0.139 |
| 光熱費 | -0.030 | +0.728 |
| 保健医療費 | +0.545 | +0.063 |
PC1:食料費(+0.593)・教育費(+0.588)・保健医療費(+0.545)に大きな正の重み、 住居費(-0.063)・光熱費(-0.030)はほぼゼロ → 「食料・教育・保健医療への支出水準」を表す軸。 PC1 のスコアが高い県はこれら 3 費目への支出が相対的に多い県と読めます。
PC2:光熱費(+0.728)に大きな正の重み、 住居費(-0.667)に大きな負の重み → 「光熱型の支出 vs 住居型の支出」の対比軸。 PC1 では捉えられなかった別の軸を、 重みの大きさ・符号から「何 vs 何の対比か」と読み取るのがローディング解釈の基本です。
💡 主成分の解釈にはドメイン知識が必要。 重みの大きさ・符号を見て、 「この成分は何を表しているか」を仮説的に解釈し、 散布図と組み合わせて確認します。
合成 4 次元データの固有値から累積寄与率を計算する。
| PC | 固有値 | 寄与率 | 累積 |
|---|---|---|---|
| PC1 | 4.0 | 0.50 | 0.50 |
| PC2 | 2.4 | 0.30 | 0.80 |
| PC3 | 1.2 | 0.15 | 0.95 |
| PC4 | 0.4 | 0.05 | 1.00 |
1 2 3 4 5 6 | import numpy as np lam = np.array([4.0, 2.4, 1.2, 0.4]) ratio = lam / lam.sum() cum = ratio.cumsum() print(f"寄与率: {ratio}") print(f"累積: {cum}") |
💬 手計算 (Step 2) と Python 出力が完全一致。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler # データの標準化(重要!) scaler = StandardScaler() X_std = scaler.fit_transform(X) # PCA 実行 pca = PCA(n_components=2) # 主成分数を指定 Z = pca.fit_transform(X_std) # 寄与率 print(f'寄与率: {pca.explained_variance_ratio_}') print(f'累積寄与率: {pca.explained_variance_ratio_.cumsum()}') # 主成分軸(固有ベクトル) print(f'主成分軸:\n{pca.components_}') # 固有値 print(f'固有値: {pca.explained_variance_}') |
1 2 3 | pca = PCA(n_components=0.95) # 累積寄与率95%まで Z = pca.fit_transform(X_std) print(f'採用された主成分数: {pca.n_components_}') |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import numpy as np # 1. 中心化 X_centered = X - X.mean(axis=0) # 2. 共分散行列 cov_matrix = np.cov(X_centered, rowvar=False) # 3. 固有値分解 eig_vals, eig_vecs = np.linalg.eigh(cov_matrix) # 4. 降順ソート order = np.argsort(eig_vals)[::-1] eig_vals = eig_vals[order] eig_vecs = eig_vecs[:, order] # 5. 射影 Z = X_centered @ eig_vecs # 寄与率 ratio = eig_vals / eig_vals.sum() |
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 | # ── この抜粋で使う主成分分析の結果を用意します ── import pandas as pd import matplotlib.pyplot as plt from sklearn.decomposition import PCA 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'] == 2023] # 2023 年の 47 都道府県 feature_names = ['A1101', 'A1303', 'A4101', 'L3221'] X_std = StandardScaler().fit_transform(df[feature_names].astype(float)) pca = PCA(n_components=2) Z = pca.fit_transform(X_std) fig, ax = plt.subplots(figsize=(10, 8)) ax.scatter(Z[:, 0], Z[:, 1], alpha=0.5) # 変数を矢印で for i, name in enumerate(feature_names): ax.arrow(0, 0, pca.components_[0, i] * 3, pca.components_[1, i] * 3, color='red', head_width=0.05) ax.text(pca.components_[0, i] * 3.2, pca.components_[1, i] * 3.2, name) ax.set_xlabel(f'PC1 ({pca.explained_variance_ratio_[0]*100:.1f}%)') ax.set_ylabel(f'PC2 ({pca.explained_variance_ratio_[1]*100:.1f}%)') |
単位が違う変数(kg と cm)をそのまま PCA すると、 単位の大きい変数が支配的に。 必ず標準化してから実施。
PCA は線形変換。 曲線的なパターンは見逃します。 そのときは Kernel PCA、 t-SNE、 UMAP、 Autoencoder を。
主成分は合成変数で、 元の変数ほど直感的でないことがある。 特に loading の重みが似た値なら解釈が難しい。 回転(varimax 回転、 因子分析)を検討。
分散を最大化するため、 外れ値の影響を受けやすい。 RobustPCA や事前の外れ値除去を。
PCA は教師なし。 「分散が大きい方向」が「目的変数の予測に有用」とは限らない。 PCR(主成分回帰)より PLS のほうが優れることも。
固有ベクトルは符号が反転しても同じ主成分。 異なる環境で計算すると符号が違うことが。 解釈時に注意。
120年以上の歴史を持ち、 現代のデータサイエンスの中核的手法として使われ続けています。
sklearn.decomposition.PCA(標準)1 2 3 4 5 6 7 8 9 10 11 12 | import pandas as pd from sklearn.preprocessing import StandardScaler 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].drop(columns=['SSDSE-B-2026']) # 2023年度・47都道府県 X = df[['L322101','L322102','L322103','L322106','L322108']] # 食料/住居/光熱・水道/保健医療/教育 Xs = StandardScaler().fit_transform(X) pca = PCA(n_components=3).fit(Xs) print('寄与率', pca.explained_variance_ratio_) print('累積', pca.explained_variance_ratio_.cumsum()) print('ローディング\n', pd.DataFrame(pca.components_.T, index=X.columns, columns=['PC1','PC2','PC3']).round(3)) |
numpy.linalg.svd 直書き(教育的)1 2 3 4 5 6 | import numpy as np Xc = Xs - Xs.mean(axis=0) U, S, Vt = np.linalg.svd(Xc, full_matrices=False) loadings = Vt.T scores = U * S # = Xc @ Vt.T print((S**2 / (S**2).sum())[:3]) |
scipy.linalg.eigh による固有値分解1 2 3 4 5 | from scipy.linalg import eigh cov = np.cov(Xs, rowvar=False) eigvals, eigvecs = eigh(cov) order = np.argsort(eigvals)[::-1] print(eigvals[order]) |
KernelPCA(非線形多様体)1 2 | from sklearn.decomposition import KernelPCA kpca = KernelPCA(n_components=2, kernel='rbf', gamma=0.1).fit_transform(Xs) |
SparsePCA / FactorAnalysis(解釈性向上)1 2 3 4 | from sklearn.decomposition import SparsePCA, FactorAnalysis spca = SparsePCA(n_components=3, alpha=1.0, random_state=42).fit(Xs) fa = FactorAnalysis(n_components=3).fit(Xs) print(pd.DataFrame(spca.components_.T, index=X.columns).round(2)) |
IncrementalPCA(大規模データのストリーム処理)1 2 3 4 | from sklearn.decomposition import IncrementalPCA ipca = IncrementalPCA(n_components=3, batch_size=10) for i in range(0, len(Xs), 10): ipca.partial_fit(Xs[i:i+10]) |
StandardScaler で z-score 化してから PCA。主成分分析(Principal Component Analysis, PCA)は、 多次元データの「分散が最大になる方向」を新しい軸として、 元の変数を組み替える手法。 次元削減と特徴抽出の基本ツール。
左:元の2変数(食料費と住居費)の散布図。 赤い矢印が PC1(最大分散方向)。
右:PCA 後、 データが PC1/PC2 という新しい直交軸上に再配置される。 もはや「食料費」「住居費」ではなく、 合成変数になっています。
💡 PCAは回転と考えられます。 「元の軸」を「データの最大分散方向」に回転させ、 新しい軸を作る。 情報損失を最小にしながら次元を減らせます。
100変数のデータを、 寄与の大きい数個の主成分で要約。 ストレージ削減、 可視化、 学習高速化。
高次元データを2次元/3次元に圧縮して散布図化。 クラスタや異常を視覚的に発見。
相関の強い変数群を独立な主成分に置き換える。 回帰モデルの安定化。
新しい「合成変数」を作り、 元の変数では見えなかった「潜在因子」を発見。
寄与の小さい成分はノイズ。 削ることでデータをスムージング。
各変数から平均を引く。 場合によって標準偏差で割る(標準化):
$$ x'_i = \frac{x_i - \bar{x}}{s} $$
単位が違う変数を扱う場合は標準化必須。 単位が同じなら中心化のみでもOK。
$$ \Sigma = \frac{1}{n-1} X^T X $$
p個の変数に対して p×p の対称行列。 対角成分が各変数の分散、 非対角が共分散。
$$ \Sigma = V \Lambda V^T $$
$$ Z = X \cdot V $$
元データを新しい軸(主成分)に射影。 これが「主成分得点」。
大規模データでは特異値分解(SVD)で実装するのが一般的:
$$ X = U S V^T $$
V が主成分、 S²/(n-1) が固有値(S は特異値の対角行列。 共分散行列 Σ とは別物)。 sklearn の PCA は内部で SVD を使っている。
1. 標準化を忘れる。「人口(万人)」と「失業率(%)」を素のまま PCA すると、 人口の桁が圧倒的に大きいため、 第 1 主成分が「人口の方向」とほぼ一致してしまい、 他の指標が全く反映されません。 StandardScaler(z 化)または RobustScaler を必ず通しましょう。
2. 主成分の符号反転を気にしない。PCA の固有ベクトルは符号が定まらないため、 ライブラリ・乱数によって PC1 が反転することがあります。 解釈で「PC1 が大きい県」と書くなら、 必ずローディングを確認して「PC1 が高い → ◯◯ が高い」の対応を明示しましょう。
3. 累積寄与率だけで主成分数を決める。「80% を超えるまで」という閾値は経験則であり、 サンプル数や目的によって変えるべきです。 スクリープロットの肘、 カイザー基準(固有値 ≥ 1)、 並列分析(parallel analysis)、 CV 損失の最小点を併用しましょう。
4. 線形変換以外を試さない。三日月型・ドーナツ型のように非線形多様体上のデータは、 PCA では分散最大方向に「貫通」してしまい、 構造を捉えられません。 Kernel PCA・t-SNE・UMAP・Isomap などの非線形手法も比較しましょう。
5. PC スコアを使った回帰(PCR)で解釈を捨てる。多重共線性の解消には便利ですが、 「PC1 の係数が 0.3」と言われても元の変数への落とし込みが難しいです。 解釈優先なら Ridge・Lasso、 もしくは Sparse PCA を検討しましょう。
6. 外れ値で第 1 主成分を奪われる。1 県(例:東京)が他県より極端な値を持つと、 PC1 がほぼ「東京の方向」になり、 残りの分散が捉えにくくなります。 RobustPCA や、 外れ値を除いた感度分析を行いましょう。
7. テストデータで fit_transform を再実行する。訓練データで学習した PCA は、 テストには transform のみ適用しなくてはいけません。 テストで fit すると、 異なる回転行列が出てしまい予測モデルが壊れます。 sklearn Pipeline を使えば自動で正しい順序になります。
PCA を一言で言い直すと、 互いに強く相関した変数の束を「代表選手(合成変数)」1 本にまとめる操作です。 相関が強いということは「同じ情報を重複して持っている」ということ。 その重複を、 分散を最大化する方向へ座標を回転させることで 1 本の軸に集約します。
元の変数 $x_1,\dots,x_p$ は「たまたま観測に使った軸」にすぎません。 PCA はデータ自身が最もばらつく方向を新しい第 1 軸に選び直します。 つまり「観測者が決めた軸」から「データが決めた軸」への直交回転です。 回転なので情報(総分散)は保存され、 ただ分散の配分が先頭の主成分に偏るように並べ替えられるだけです。 詳しくは 固有値・固有ベクトル と 共分散行列 を参照。
ある方向に射影したとき、 点がよく散らばる(分散が大きい)ほど、 その方向はサンプル同士を見分ける力が強いと言えます。 逆に、 どの県も同じ値になる方向(分散ゼロ)は、 見ても何も区別できず情報がありません。 だから「分散が大きい方向 = よく区別できる方向 = 情報が多い方向」とみなすのが PCA の発想です。 これは 分散 を情報量の代理指標として使う、 という約束の上に成り立っています(後述の落とし穴も参照)。
共分散行列 $\Sigma$ を「データの楕円形の広がり」を表す行列だと思うと、 その固有ベクトルは楕円の主軸(長軸・短軸)の向き、 固有値は各主軸方向の広がり(分散)の大きさに一致します。 楕円が細長い(=相関が強い)ほど、 長軸方向の固有値が突出し、 1 本でほぼ説明できる──これが次元削減が効く状況です。 このページ上部の 🎮 ウィジェットで「相関 強い」を選ぶと、 PC1 の寄与率が跳ね上がるのは、 まさにこの楕円が細長くなるからです。
キーワード索引と同じ 6 指標を標準化して PCA した実測ローディング(固有ベクトル成分)は次の通りです。 人口系の 5 指標(総人口・65歳以上人口・出生数・婚姻件数・一般診療所数)が PC1 に各 |0.44| 前後で均等に乗り、 消費支出だけが浮きます。
| 指標 | PC1 ローディング | PC2 ローディング |
|---|---|---|
| 総人口 | −0.44 | −0.06 |
| 65歳以上人口 | −0.44 | −0.06 |
| 出生数 | −0.44 | −0.09 |
| 婚姻件数 | −0.44 | −0.07 |
| 一般診療所数 | −0.44 | −0.10 |
| 消費支出(二人以上世帯) | −0.17 | +0.98 |
人口系 5 指標は互いに強く相関する「1 つの束」なので、 PC1 という 1 本の合成変数(=人口規模軸)に集約されます。 一方、 消費支出は世帯単位の指標で人口規模とはほぼ独立に動くため、 PC1 にほとんど乗らず、 PC2(消費水準軸)として独立に立ち上がります。 「相関の強い変数を少数の合成変数へ」という PCA の直感が、 実データでそのまま観測できる好例です。 ※固有ベクトルの符号は数学的に任意なので、 マイナス符号自体に意味はありません。
既存の「落とし穴」章に加え、 PCA を鵜呑みにすると危険なポイントを実測値つきで補強します。 特に「標準化必須」と「分散最大 ≠ 重要」は、 コンペで PCA を使うときに最も事故が多い箇所です。
| 主成分 | 固有値 λ | 寄与率 | 累積寄与率 |
|---|---|---|---|
| PC1 | 5.040 | 84.0% | 84.0% |
| PC2 | 0.879 | 14.6% | 98.6% |
| PC3 | 0.063 | 1.0% | 99.7% |
| PC4 | 0.014 | 0.2% | 99.9% |
| PC5 | 0.004 | 0.1% | 100.0% |
| PC6 | 0.000 | 0.0% | 100.0% |
固有値の合計は変数の数と一致します(標準化データなので $\sum\lambda_i = 6$)。 カイザー基準(λ≥1)なら PC1 のみ、 累積 80% ルールなら PC1〜PC2 が採用となり、 基準によって残す本数が変わることも実測で確認できます。
PCA には 2 通りの計算経路があります。 (a) 共分散行列 $\Sigma$ の固有値分解 $\Sigma = V\Lambda V^\top$(固有値・固有ベクトル参照)と、 (b) 中心化データ行列 $X$ の特異値分解(SVD) $X = U S V^\top$ です。 両者は $\lambda_k = s_k^2/(n-1)$ で対応し、 得られる主成分軸 $V$ は同一になります。 実務では共分散行列を作らず $X$ を直接 SVD する方が数値的に安定で($\Sigma$ を作ると条件数が 2 乗される)、 scikit-learn の PCA も内部で SVD を使います。 SVD は共分散行列を明示的に作らないぶんメモリ効率もよく、 高次元・疎データに向きます。
第 $k$ 主成分の寄与率は $\lambda_k/\sum_i\lambda_i$、 上位から足し上げた累積寄与率が「何本で総分散の何%を説明したか」を表します。 固有値を大きい順に折れ線で並べたスクリープロットで「急落してなだらかになる肘」を探すのが古典的な主成分数決定法です。 上の SSDSE 実測では PC1→PC2→PC3 が 5.04→0.879→0.063 と 2 段階で急落し、 肘が明瞭に 2 本目に現れます。 統計的根拠を求めるなら、 ランダムデータの固有値分布と比較する並行解析(parallel analysis)が有効です。
見た目は似ていますが目的が逆向きです。 PCA は観測変数を合成して分散を最大化する(変数 → 成分)のに対し、 因子分析 は観測の背後に潜在因子を仮定し、そこから観測が生成される(因子 → 変数)というモデルを立てます。 PCA は全分散(共通分散+独自分散+誤差)を分解し、 因子分析は共通分散のみを抽出して独自分散・誤差を分離します。 「データ圧縮・可視化」なら PCA、 「心理尺度など潜在構造の推定」なら因子分析、 が使い分けの目安です。
Kernel PCA は、 データを高次元特徴空間へ写像してから PCA を行うことで非線形な主成分を取り出します。 実際には写像を明示せず、 内積をカーネル関数(RBF など)で置き換えるカーネルトリックで計算します。 三日月・同心円のように線形 PCA では潰れる構造を、 曲がった主成分で展開できます。 コストはサンプル数 $n$ に対する $n\times n$ カーネル行列($O(n^2)$ メモリ)で、 大規模データでは近似が必要です。
Robust PCA(Candès ら 2009)は、 データ行列を低ランク成分 $L$ + 疎な外れ値成分 $S$ に分解し($X = L + S$)、 外れ値やスパイクの影響を $S$ に隔離して汚染されていない低次元構造 $L$ を取り出します。 通常の PCA が外れ値 1 点で軸を奪われるのに対し、 破損・欠測・スパイクに強いのが利点で、 監視カメラ映像の背景/前景分離などで実用化されています(このページ内リンクは未整備のため用語のみ紹介)。
白色化は、 主成分に射影したあと各成分を固有値の平方根で割り、 共分散行列を単位行列に変換する前処理です($\tilde{Z} = \Lambda^{-1/2} V^\top X$)。 全方向の分散を 1 に揃えて相関を消すため、 勾配法の収束を速めたり、 独立成分分析(ICA)の前処理として使われます。 ただし小さい固有値方向を等倍に引き伸ばすため、 ノイズを増幅する副作用があり、 実務では下位成分を捨ててから白色化することが多いです。 なお PCA では主成分どうしは無相関ですが、 白色化はさらに「分散も等しく」するステップです(無相関 ≠ 独立である点は 共分散 の注意点と同じ)。
※ 本節の SVD・白色化・ロバスト PCA の一部は用語集内に個別ページが未整備のため、 テキストでの紹介にとどめています(固有値・Kernel PCA・因子分析・標準化・次元削減 は個別ページあり)。
主成分分析(PCA) がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。
🌐 統計・データサイエンス › 教師なし学習 › 次元削減 › 主成分分析
中心に 主成分分析(PCA) を置き、 そこから 因子分析・クラスタリング・共分散・分散・標準化・多重共線性対策 など 計 13 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語とあとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。
大きな円が小さな円を包含する Circle Packing 図。 「主成分分析(PCA)」は緑色でハイライト。
長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「主成分分析(PCA)」は緑色でハイライト。
| マップ | 分かること | こんな時に見る |
|---|---|---|
| 🔗 関係マップ | 手法間の横の関係(前提→発展→応用) | 「次に何を学べばよい?」 学習順序の判断 |
| ⭕ 包含マップ | 分類体系の入れ子構造(上位⊃下位) | 「この手法はどんなジャンルに属する?」 |
| 🌳 ツリーマップ | 分野の規模比較(面積=ボリューム) | 「データサイエンス全体の俯瞰像」 |
💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは 主成分分析 の隣に何が並ぶかを、 包含マップとツリーマップは 統計・データサイエンス → 次元削減 → 主成分分析 という入れ子の位置を示します。 「次元削減には他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。
PCA は高次元データを少数の合成軸 (主成分) に射影する手法で、 次元削減・可視化・前処理として隣接手法に組み込まれる。
SSDSE-B-2026 を用いた演習では、 「主成分分析」 を中核に据えて上記の上流・並列・下流の手法を実データで連結する経験を積むと、 単独の手法暗記より実務的応用力が身につく。
「pca」を含む手法選択は、 データの性質・分析目的・運用制約の 3 軸で決まる。 以下に典型シナリオと対応する手法の組合せを示す。
| シナリオ | 重視する観点 | 候補手法 |
|---|---|---|
| データが大規模 (n が多い、 高次元) | 計算コスト / メモリ / 並列化が必要 | IncrementalPCA・SVD ベースの PCA 等 |
| 外れ値が多い / ノイズあり | 頑健性 / 外れ値除去 / 中央値ベース | Robust PCA・外れ値除去後の PCA 等 |
| 解釈性を重視する | 少数変数の線形結合 / 潜在因子 | Sparse PCA・因子分析 等 |
| 予測精度を最優先する(教師あり) | 目的変数との関連 / 交差検証 | PLS・LDA・Lasso 等(PCA は教師なしのため精度を保証しない) |
| 非線形構造が疑われる | 多様体 / 局所構造の保存 | Kernel PCA・t-SNE・UMAP 等 |
| リアルタイム/オンライン処理 | ストリーミング / 軽量モデル / 逐次更新 | IncrementalPCA(partial_fit で逐次更新) 等 |