【Python入門:主成分分析編#4】scikit-learnでサクッとPCA(主成分分析) ― たった2行で次元圧縮
手計算を卒業して、実践へ
以下の3回で、PCAの仕組みを一から説明しました。
NumPyで手計算した経験があるからこそ、ライブラリが「裏で何をしているか」がわかります。
今回は、scikit-learnを使って、PCAを効率的に実行する方法を学びましょう。
手計算で何十行も書いていたコードが、たった2行になります。
🎯 この記事で学べること
scikit-learnでPCAを実行する基本的な流れ
寄与率・固有値・固有ベクトルの取り出し方
主成分負荷量の計算方法
散布図とスクリープロットの作成
📦 準備:ライブラリとデータ
ライブラリの読み込み
以下、コードです。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCAデータの準備
おなじみのIrisデータセットを使います。4つの特徴量を持つ150サンプルのデータです。
以下、コードです。
# Irisデータセットを読み込み
iris = load_iris()
X = iris.data
y = iris.target
特徴量名 = iris.feature_names
品種名 = iris.target_names
# 標準化(PCAの前処理として必須)
scaler = StandardScaler()
X_標準化 = scaler.fit_transform(X)
print(f"データの形状: {X_標準化.shape}")
print(f"特徴量: {特徴量名}")以下、実行結果です。
データの形状: (150, 4)
特徴量: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
ポイント: PCAは分散を見る手法なので、標準化してスケールを揃えることが重要です。
🚀 scikit-learnでPCAを実行する
基本の2行
scikit-learnのAPIはシンプルです。fitで学習、transformで変換。fit_transformなら一度に両方できます。
以下、コードです。
# ① PCAオブジェクトを作成(2次元に圧縮)
pca = PCA(n_components=2)
# ② 実行!
Z = pca.fit_transform(X_標準化)
# 結果を確認(先頭5行)
print(Z[:5])以下、実行結果です。
[[-2.26470281 0.4800266 ]
[-2.08096115 -0.67413356]
[-2.36422905 -0.34190802]
[-2.29938422 -0.59739451]
[-2.38984217 0.64683538]]
4次元のデータが2次元に変換されました!
前回までNumPyで行った「共分散行列の計算」「固有値分解」「主成分得点の算出」が、この2行に凝縮されています。
📊 結果を取り出す
PCAオブジェクトには、分析結果がすべて格納されています。主要な属性を見ていきましょう。
寄与率と固有値
以下、コードです。
print("=== 各主成分の情報 ===")
for i in range(len(pca.explained_variance_ratio_)):
寄与率 = pca.explained_variance_ratio_[i]
固有値 = pca.explained_variance_[i]
print(f"PC{i+1}: 寄与率 = {寄与率*100:.2f}%, 固有値 = {固有値:.4f}")
# 累積寄与率
累積 = np.cumsum(pca.explained_variance_ratio_)
print(f"\n累積寄与率: {累積[-1]*100:.2f}%")以下、実行結果です。
=== 各主成分の情報 ===
PC1: 寄与率 = 72.96%, 固有値 = 2.9381
PC2: 寄与率 = 22.85%, 固有値 = 0.9202
累積寄与率: 95.81%
2つの主成分で、元データの情報の約96%を保持しています。4次元→2次元への圧縮としては十分な結果です。
主成分の方向(固有ベクトル)
components_属性には、各主成分の方向を示す固有ベクトルが格納されています。
以下、コードです。
# 固有ベクトルをDataFrameで見やすく
固有ベクトルDF = pd.DataFrame(
pca.components_,
index=['PC1', 'PC2'],
columns=特徴量名
)
print(固有ベクトルDF.round(3))以下、実行結果です。
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
PC1 0.521 -0.269 0.580 0.565
PC2 0.377 0.923 0.024 0.067
この表の読み方:
PC1: petal length、petal width、sepal lengthの係数が大きい → 花のサイズ全般を表す軸
PC2: sepal widthの係数が突出 → がく片の幅を表す軸
主成分負荷量を計算する
固有ベクトルと主成分負荷量は別物です。主成分負荷量は「元の変数と主成分の相関」を表し、解釈しやすい指標です。
以下、コードです。
# 主成分負荷量 = 固有ベクトル × √固有値
負荷量 = 固有ベクトルDF.T * np.sqrt(pca.explained_variance_)
print("=== 主成分負荷量 ===")
print(負荷量.round(3))以下、実行結果です。
=== 主成分負荷量 ===
PC1 PC2
sepal length (cm) 0.893 0.362
sepal width (cm) -0.462 0.886
petal length (cm) 0.995 0.023
petal width (cm) 0.968 0.064
負荷量が ±0.7 以上なら「強い関連」と解釈できます。
PC1: petal length (0.995)、petal width (0.968)、sepal length (0.893) と強く関連
PC2: sepal width (0.886) と強く関連
📈 可視化する
主成分得点の散布図
2次元に圧縮したデータを散布図で確認しましょう。
以下、コードです。
plt.figure(figsize=(10, 8))
# 品種ごとに色分け
colors = ['#E74C3C', '#2ECC71', '#3498DB']
for i, (name, color) in enumerate(zip(品種名, colors)):
mask = y == i
plt.scatter(
Z[mask, 0], Z[mask, 1],
c=color, label=name, s=80, alpha=0.7
)
plt.xlabel(f'PC1 ({pca.explained_variance_ratio_[0]*100:.1f}%)')
plt.ylabel(f'PC2 ({pca.explained_variance_ratio_[1]*100:.1f}%)')
plt.title('PCA: Irisデータセットの2次元表現')
plt.legend(title='品種')
plt.grid(True, alpha=0.3)
plt.axhline(y=0, color='gray', linewidth=0.5)
plt.axvline(x=0, color='gray', linewidth=0.5)
plt.show()以下、実行結果です。

3品種がきれいに分離されていることが確認できます。特にsetosaは他の2種と完全に分かれています。
これが次元削減の威力です。4次元空間では見えなかったパターンが、2次元に圧縮することで可視化できました。
スクリープロット
すべての主成分を抽出して、最適な主成分数を判断するためのスクリープロットを作成します。
以下、コードです。
# 全主成分を抽出(n_componentsを指定しない)
pca_full = PCA()
pca_full.fit(X_標準化)
# プロット作成
fig, axes = plt.subplots(2, 1, figsize=(10, 10))
x = np.arange(1, len(pca_full.explained_variance_) + 1)
# 上段:固有値
axes[0].bar(x, pca_full.explained_variance_, color='steelblue')
axes[0].set_xlabel('主成分')
axes[0].set_ylabel('固有値')
axes[0].set_title('スクリープロット')
axes[0].set_xticks(x)
# 下段:寄与率と累積寄与率
累積寄与率 = np.cumsum(pca_full.explained_variance_ratio_) * 100
axes[1].bar(x, pca_full.explained_variance_ratio_ * 100,
label='寄与率', color='steelblue')
axes[1].plot(x, 累積寄与率, 'ro-', markersize=10, linewidth=2,
label='累積寄与率')
axes[1].axhline(y=80, color='green', linestyle='--', label='80%ライン')
axes[1].set_xlabel('主成分')
axes[1].set_ylabel('寄与率 (%)')
axes[1].set_title('寄与率と累積寄与率')
axes[1].set_xticks(x)
axes[1].legend()
plt.tight_layout()
plt.show()以下、実行結果です。

このグラフから、「エルボー法」や「累積寄与率80%以上」といった基準で、最適な主成分数を判断できます。
まとめ
scikit-learnを使ったPCAの実行方法をお話ししました。
基本の流れ:
PCA(n_components=2) でオブジェクト作成
fit_transform(X) で実行
属性から寄与率や固有ベクトルを取得
重要なポイント:
事前にデータを標準化する
explained_variance_ratio_ で寄与率を確認
主成分負荷量は components_.T * √explained_variance_ で計算
📺 次回予告
次回は、PCAと似ているようで異なる「因子分析」を取り上げます。
PCAは「データを要約する」
因子分析は「背後にある構造を見つける」
両者の違いを理解することで、分析目的に応じた手法選択ができるようになります。
お楽しみに!
📚 参考にした情報源
最後まで読んでいただきありがとうございました! 「スキ」を押していただけると励みになります 🙌
