論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
散布図
Scatter Plot
2変数を x軸・y軸にプロットして関係を視覚化。相関や非線形パターン、外れ値の確認に必須。
可視化scatter散布図
📍 文脈💡 30秒結論📖 詳しく

📍 あなたが今見ているもの

論文中に 「散布図」として登場する用語。

散布図 とは:2変数を x軸・y軸にプロットして関係を視覚化。相関や非線形パターン、外れ値の確認に必須。

💡 30秒で分かる結論

📖 もっと詳しく

散布図(scatter plot)は、 2変数の関係を視覚化する最基本ツール。 横軸 x、 縦軸 y にデータ点をプロットします。 統計分析を始めるときに 必ず最初に描くべき図 です。

判別ポイント

必須習慣:相関係数を計算する前に、 必ず散布図を描く。 同じ r = 0.5 でも、 きれいな直線関係と、 外れ値による偽の相関は全く違います。 Anscombe の4組(r が同じでも散布図が全然違う有名な例)を見ると痛感します。

応用:(i) 単回帰の直線を重ねる、 (ii) hex bin で密度を可視化(点が多すぎる場合)、 (iii) seaborn の jointplot で周辺分布も同時に表示。

👁️ 直感 — 散布図は「2変数の関係が見える」

散布図(scatter plot)は、 2つの量的変数の関係を点で可視化する基本グラフ。 各点が1つの観測単位(人、 県、 商品など)を表します。

散布図の基本

47都道府県の食料費(横軸)と教育費(縦軸)の関係。 点が右上がりに広がっていて、 食料費が高い県は教育費も高い傾向(r = 0.728)。

💡 散布図は相関分析・回帰分析の前段階として必ず描くべきグラフ。 「相関係数 r が大きい」と言う前に、 必ず散布図で関係の形を確認しましょう。

📊 散布図で見える6つの代表パターン

散布図の形から、 2変数の関係を診断できます:

散布図パターン
パターン 特徴 適切な分析
強い正の相関右上がりにまとまるPearson 相関、 線形回帰
弱い正の相関右上がりだが散らばるPearson 相関 + 信頼区間
負の相関右下がりにまとまる同上
無相関円形に分布独立性検定
非線形(U字、 周期)曲線パターン非線形回帰、 Spearman、 相関比
外れ値少数の極端な点ロバスト回帰、 除去 or 別分析

🎈 バブルチャート — 3変数を1枚で表現

点のサイズや色で3つ目の変数を表現するのがバブルチャート。 SSDSE データで食料費×教育費の関係に、 「総人口」を点のサイズと色で重ねます。

バブルチャート

人口が多い大都市府県(東京、 神奈川など)は大きな円で表示され、 食料費・教育費も比較的高い位置に。 3次元の情報を2D上に圧縮できる強力な可視化。

Python での実装

🎯 解説: SSDSE-B-2026 の 47 都道府県データを 2 軸の点で表現し、 2 変数の関係(正・負・無相関、 線形・非線形、 外れ値)を視覚的に把握する。 散布図は探索的データ解析(EDA)の出発点。
📥 入力例: data/raw/SSDSE-B-2026.csv x = df['A1101'](総人口) y = df['A1301'](65歳以上人口) n = 47 県
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import matplotlib.pyplot as plt

plt.scatter(x, y,
    s=sizes * 0.1,           # 点のサイズ
    c=color_var,             # 点の色(連続値)
    cmap='viridis',          # カラーマップ
    alpha=0.6,
    edgecolors='white')
plt.colorbar(label='色変数')

# seaborn でより簡潔に
import seaborn as sns
sns.scatterplot(x='食料費', y='教育費', size='総人口', hue='地域', data=df)
📤 実行例: 散布図(人口 vs 高齢者人口) 右肩上がりの強い正の関係 東京・神奈川・大阪が右上に集中 鳥取・島根が左下
💬 読み方: 人口が多い県ほど高齢者数も多い(当然)。 ただし「率」(高齢化率)と区別すること。 点が直線状に並ぶ → 線形相関。 U 字状 → 非線形。 はずれ値は個別ラベルで確認。

🔷 大量データには hexbin — 重なり問題を解決

データ点が数千・数万になると、 通常の散布図では点が重なって何も見えません。 そんなときはhexbin(六角形ビン)

hexbin

2D空間を六角形のビンで区切り、 各ビン内のデータ数を色で表現。 大量データの密度パターンが見えます。

その他の対処法

🎨 散布図の拡張

① 散布図行列(pairs plot)

変数が3つ以上ある時、 すべてのペアの散布図を一気に表示:

🎯 解説: matplotlib.pyplot.scatter で SSDSE-B-2026 の 2 変数散布図を最もシンプルに描画。 alpha でハイライト・色で第 3 変数を表現できる。
📥 入力例: data/raw/SSDSE-B-2026.csv x = df['A1101'] y = df['B1101'](県内総生産)
1
2
import seaborn as sns
sns.pairplot(df[['食料費', '教育費', '住居費', '光熱費']], kind='reg')
📤 実行例: 47 点の散布図 右肩上がりの分布 東京が極端な右上外れ値
💬 読み方: 点が密集する領域は alpha=0.5 で重なりを可視化。 ラベル付け(県名)が必要なら annotate で個別に追加。 外れ値が回帰直線を引っ張らないか必ず確認。

② カテゴリ変数で色分け

地域・性別・カテゴリで色分けすると、 群間差が見える:

sns.scatterplot(x='食料費', y='教育費', hue='地域', style='都市規模', data=df)

③ LOWESS(局所重み付き回帰)

非線形な関係を平滑化した曲線で表示:

🎯 解説: seaborn.scatterplot で hue(色)・size(大きさ)・style(マーカー)を一括設定。 多次元情報を 1 つの散布図に詰め込める拡張機能。
📥 入力例: data/raw/SSDSE-B-2026.csv x='A1101', y='B1101' hue=地域区分(北海道~九州)
1
2
3
4
sns.regplot(x='x', y='y', data=df, lowess=True)
# または statsmodels
from statsmodels.nonparametric.smoothers_lowess import lowess
smoothed = lowess(y, x, frac=0.3)
📤 実行例: 散布図 + 地域別の色凡例 関東圏(赤)が右上に集中 地方(青)が左下
💬 読み方: 色分けで地域差が直感的に見える。 hue が連続変数だとカラーマップ、 カテゴリだと離散色。 凡例を必ず表示。 色覚多様性に配慮して colormap を選ぶ。

④ 信頼区間付き回帰直線

sns.regplot(x='食料費', y='教育費', data=df, ci=95) # 95%信頼区間が陰影で表示される

⑤ 結合プロット(jointplot)

散布図 + ヒストグラム + 統計量を1枚に:

sns.jointplot(x='食料費', y='教育費', data=df, kind='reg') # kind: 'scatter', 'hex', 'kde', 'reg', 'resid', 'hist'

🤖 機械学習での散布図

① EDA(探索的データ分析)

機械学習の前段階で、 各特徴量ペアの関係を散布図行列で確認。 「強い相関がある」「外れ値がある」「非線形だ」などを発見。

② クラスタリング結果の可視化

k-means や DBSCAN の結果を、 色分け散布図で確認。 2次元または PCA で2次元に圧縮してから描画:

🎯 解説: 散布図行列(pairplot)で SSDSE-B-2026 の数値変数全組み合わせを一括描画。 多変数間の関係性を一目で把握する EDA の鉄板手法。
📥 入力例: data/raw/SSDSE-B-2026.csv columns=['A1101','A1301','B1101','C1101'] 4 変数 × 4 変数 = 16 パネル
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA

# 高次元データを2次元に
pca = PCA(n_components=2)
X_2d = pca.fit_transform(X)

# クラスタリング
km = KMeans(n_clusters=3)
labels = km.fit_predict(X)

plt.scatter(X_2d[:, 0], X_2d[:, 1], c=labels, cmap='viridis')
📤 実行例: 4×4 マトリクス 対角: ヒストグラム 非対角: 散布図 人口系変数間は強い線形関係
💬 読み方: 対角はその変数の分布、 非対角はペア相関。 強い線形関係が見えるペアは多重共線性に注意。 変数が 10 を超えると見づらいので相関行列ヒートマップを併用。

③ 残差プロット

回帰モデルの残差 vs 予測値を散布図にする。 ランダムなら適合良、 パターンがあればモデル改善の余地:

predictions = model.predict(X) residuals = y - predictions plt.scatter(predictions, residuals, alpha=0.5) plt.axhline(0, color='red') plt.xlabel('予測値') plt.ylabel('残差')

④ QQプロット

残差が正規分布に従うか確認する散布図:

🎯 解説: 回帰直線と 95% 信頼区間付きの散布図を seaborn.regplot で描画。 関係性の方向・強さ・不確実性を一画面で表現。
📥 入力例: data/raw/SSDSE-B-2026.csv x='A1101', y='B1101' ci=95
1
2
3
from scipy import stats
stats.probplot(residuals, dist='norm', plot=plt)
# 点が直線上 → 正規分布
📤 実行例: 散布図 + 青回帰直線 + 薄青信頼帯 傾き 8.05、 R² 0.93
💬 読み方: 信頼帯が狭い領域は推定が安定、 帯がデータ範囲外で広がる → 外挿不可。 R² が高くても残差プロットも見ること。 外れ値(東京)が直線を引っ張る場合は除外検討。

⑤ ROC曲線・精度再現率曲線

機械学習モデルの評価でも散布図的な可視化が頻出。

🔍 散布図の読み方 — 8つのチェックポイント

  1. 関係の方向:正・負・無関係
  2. 関係の強さ:点が直線にまとまる度合い
  3. 関係の形:直線か曲線か
  4. 外れ値:少数の極端な点が見えるか
  5. クラスタ:点の集まりが複数あるか(混在する集団)
  6. 異質性:ばらつきが変数の値で変わるか(不等分散)
  7. 境界・打ち切り:上限・下限に張り付く点があるか
  8. 欠損パターン:データが取れていない領域があるか

💡 散布図1枚から、 統計分析の方針(線形か非線形か、 ロバスト推定が必要か、 外れ値除去が必要か)が決まります。 数値だけ見るより必ず可視化を見る

🐍 Python での散布図描画

matplotlib(基本)

🎯 解説: plotly.express.scatter でインタラクティブ散布図を作成。 ホバーで県名・値を表示、 ズーム・選択・色分けが可能。 ダッシュボード用途に最適。
📥 入力例: data/raw/SSDSE-B-2026.csv x='A1101', y='B1101' hover_name='都道府県'
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import matplotlib.pyplot as plt

plt.figure(figsize=(8, 5))
plt.scatter(x, y, s=60, alpha=0.6, color='steelblue', edgecolors='white')
plt.xlabel('X変数')
plt.ylabel('Y変数')
plt.title('散布図のタイトル')
plt.grid(alpha=0.3)
plt.show()

# 回帰直線を追加
import numpy as np
z = np.polyfit(x, y, 1)
plt.plot(x, z[0]*x + z[1], 'r-', label=f'y={z[0]:.2f}x+{z[1]:.2f}')
plt.legend()
📤 実行例: ブラウザでインタラクティブ図 マウスホバー → 「東京都: 人口 14M, GDP 115T」
💬 読み方: 静的画像と違い、 ズーム・パン・ホバーで詳細確認可能。 HTML 出力で配布可能。 大量データ(10万点超)では描画が重くなる → datashader 推奨。

seaborn(高機能)

🎯 解説: バブルチャート(散布図 + 点サイズ)で第 3 変数を表現。 SSDSE-B-2026 で x=人口、 y=GDP、 size=高齢化率 の 3 次元情報を 2D で可視化。
📥 入力例: data/raw/SSDSE-B-2026.csv x='A1101', y='B1101' size='高齢化率'(バブル半径)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import seaborn as sns

# 基本
sns.scatterplot(x='食料費', y='教育費', data=df)

# 色・サイズ分け
sns.scatterplot(x='食料費', y='教育費', hue='地域', size='総人口', data=df)

# 回帰直線 + 信頼区間
sns.regplot(x='食料費', y='教育費', data=df)

# 散布図行列
sns.pairplot(df[['食料費', '教育費', '住居費']], diag_kind='kde')

# joint plot
sns.jointplot(x='食料費', y='教育費', data=df, kind='reg')
📤 実行例: 47 個のバブル 右上(人口多・GDP 高)は小バブル(高齢化率低) 左下は大バブル(地方の高齢化率高)
💬 読み方: バブルサイズは半径ではなく面積比例にすべき(s=value 引数)。 サイズの差が大きいと小バブルが見えなくなる → 正規化推奨。 凡例にサイズスケールを明記。

plotly(インタラクティブ)

🎯 解説: 外れ値検出付き散布図。 z-score > 3 や IQR 外の点を赤色で強調表示。 SSDSE-B-2026 で東京・大阪などの極端な県を視覚的に特定。
📥 入力例: data/raw/SSDSE-B-2026.csv z = (x - mean) / std 外れ値: |z| > 2
1
2
3
4
5
6
7
import plotly.express as px

fig = px.scatter(df, x='食料費', y='教育費',
                 size='総人口', color='地域',
                 hover_data=['都道府県'], trendline='ols')
fig.show()
# マウスホバーでデータ詳細が見える
📤 実行例: 通常点(青)+ 外れ値(赤) 東京・神奈川・大阪・愛知が赤 人口が大きく外れる
💬 読み方: 外れ値は誤データかも本当に極端な値かを区別。 SSDSE では「東京が外れ値」は事実。 除外せず log 変換で対応するか、 ロバスト回帰を使う。

🚧 散布図の落とし穴

1️⃣ 軸のスケールで見え方が変わる

軸の範囲を狭めると関係が誇張、 広げると弱く見える。 必ずデータ全体を含む範囲で描画。

2️⃣ 点が重なって見えない(overplotting)

大量データでは alpha、 jitter、 hexbin で対処。

3️⃣ 色覚多様性への配慮

赤×緑の組合せは色覚多様性で識別できない人も。 viridis、 plasma などのカラーマップを推奨。

4️⃣ 第3変数の交絡

2変数の関係に見えるものが、 第3変数の影響かもしれません。 シンプソンのパラドックスに注意。

5️⃣ 因果と相関の混同

散布図で関係が見えても、 因果ではない。 「アイスクリーム売上 vs 水難事故」の典型例(共通因:気温)。

6️⃣ 単位の異なる軸を強引に比較しない

身長 vs 体重のような異なる単位の場合、 標準化後に比較するなどの工夫が必要なことも。

📜 散布図の歴史

散布図は170年以上の歴史を持ち、 今もデータサイエンスの中核可視化として使われ続けています。

🗺️ 概念マップ — 3つの視点で体系を理解する

散布図 がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。

📍 体系階層のパス

🌐 統計・データサイエンス記述統計可視化散布図

① 🔗 関係マップ — 「他の手法とどう繋がっているか」

中心の概念から放射状に、 前提・兄弟・発展形・応用先などの関係性を矢印で結びます。 横の繋がりを見るのに最適。 ノードをドラッグ、 ホイールでズーム、 クリックで遷移

凡例:現在の用語上位カテゴリ兄弟(並列)前提発展形応用先2階層先

② ⭕ 包含マップ — 「どのカテゴリに含まれているか」

大きな円が小さな円を包含する Circle Packing 図。 「散布図」は緑色でハイライト

📍現在地:統計・データサイエンス

③ 🌳 ツリーマップ — 「面積で見るボリューム比較」

長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「散布図」は緑色でハイライト

🎯 3つのマップの使い分け

マップ 分かること こんな時に見る
🔗 関係マップ手法間の横の関係(前提→発展→応用)「次に何を学べばよい?」 学習順序の判断
⭕ 包含マップ分類体系の入れ子構造(上位⊃下位)「この手法はどんなジャンルに属する?」
🌳 ツリーマップ分野の規模比較(面積=ボリューム)「データサイエンス全体の俯瞰像」

💡 ジャストインタイム学習のヒント:3つの視点を行き来することで、 概念を多角的に理解できます。 包含マップやツリーマップはズーム/ドリルダウンで大分類から細部まで探索できます。

🔖 キーワード索引(補強・追加分)

散布図 関連の補強キーワード。 クリックで該当箇所へ:

マーカー ジッタリング 色分け 回帰線 散布図行列 透明度α 六角ビン LOWESS マージナル 対数軸

🧮 SSDSE-B 実値計算例(47都道府県データ)

47 都道府県データで散布図を体系的に作成し、 ジッタリング・色分け・回帰線・マージナル分布まで含む実例。

① 計算コード

🎯 解説: 対数軸散布図(loglog)で SSDSE-B-2026 のスケール差が大きい変数を可視化。 人口や GDP は東京と鳥取で 30 倍差があるため対数軸が有効。
📥 入力例: data/raw/SSDSE-B-2026.csv plt.xscale('log'), yscale('log') 人口・GDP は log 正規分布的
 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
30
31
32
33
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)

# 基本散布図
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
ax = axes[0, 0]
ax.scatter(df['一人当たり県民所得'], df['持ち家比率'], alpha=0.7, s=60)
ax.set_xlabel('一人当たり県民所得(千円)'); ax.set_ylabel('持ち家比率(%)')
ax.set_title('① 基本散布図')

# 第3変数で色分け
ax = axes[0, 1]
sc = ax.scatter(df['一人当たり県民所得'], df['持ち家比率'],
                c=df['人口密度'], cmap='viridis', s=60, alpha=0.8)
plt.colorbar(sc, ax=ax, label='人口密度')
ax.set_title('② 人口密度で色分け')

# 回帰線つき
ax = axes[1, 0]
sns.regplot(x='一人当たり県民所得', y='持ち家比率', data=df,
            ax=ax, scatter_kws={'alpha':0.6}, line_kws={'color':'red'})
ax.set_title('③ 回帰線(95% CI 帯)')

# 六角ビン(大きいデータ向け)
ax = axes[1, 1]
hb = ax.hexbin(df['一人当たり県民所得'], df['持ち家比率'], gridsize=10, cmap='Blues')
plt.colorbar(hb, ax=ax, label='密度')
ax.set_title('④ 六角ビン')

plt.tight_layout(); plt.savefig('scatter_4panel.png', dpi=110)
📤 実行例: log-log 散布図 ほぼ直線状(べき乗則) 東京も平均的位置に 小さい県も識別可能
💬 読み方: log-log で直線 → べき乗則 y=a·x^b。 傾きが指数 b に相当。 軸目盛は 10^0, 10^1 などの底 10 表示が標準。 0 や負値があると log を取れない(+1 シフト等が必要)。

② 期待出力

項目 参考 解釈
基本観測47点1点=1都道府県
傾向相関係数r ≈ -0.65所得高い県ほど持ち家比率低い
外れ東京高所得・低持家率右下に位置
外れ富山・福井中所得・高持家率上部

👉 値は SSDSE-B-2026 の典型値。 同じ手順で他都道府県・他変数にも適用可能。

⚠️ 落とし穴(拡張版・各 100 文字以上)

① 点が重なる(オーバープロット)
同じ位置に複数点が重なると視覚的に「1点」に見え、 実際の密度を誤認。 透明度を下げる(alpha=0.3)、 ジッタリング、 六角ビン(hexbin)、 2D KDE などで対処。 n が数万を超えると単純散布図は無意味になることが多い。 SSDSE の n=47 では問題ないが、 個票データではほぼ必須。
② 軸範囲・原点の操作で印象が変わる
軸を絞ると傾向が誇張、 広げると小さく見える。 0 を含むかどうかで全く違う印象。 必ずデータ範囲に対して適切なスケール、 必要なら軸を明示し、 ゼロ抑制(broken axis)は明記する。 散布図では原点を含めないことも多いが、 比率データなど 0 が意味を持つ場合は要注意。
③ 相関を「見た目」だけで判断
散布図で「強い相関がありそう」と思っても、 視覚は曲線関係や外れ値に騙される。 必ず数値の相関係数(Pearson / Spearman)と統計検定を併記。 Anscombe の四つ組のように、 同じ r=0.82 でも全く違う散布図が存在する。 視覚と数値を相互チェックする習慣を。
④ 因果関係と相関の混同
散布図で「X 増→ Y 増」が見えても因果の証拠ではない。 第3変数(交絡)・逆因果・選択バイアスの可能性。 因果を主張するには実験・自然実験・操作変数等の追加デザインが必要。 散布図はあくまで関連の可視化、 因果の入り口に過ぎない。
⑤ 外れ値の処理を恣意化
「分析しやすいから」と外れ値を削除すると、 結果が歪む。 まず散布図で確認し、 入力ミス/実存する極値かを判別。 実存なら(東京のような)原則含めて分析し、 sensitivity analysis で除外したケースも示す。 散布図上の外れ値こそ最も情報量が多いことが多い。
⑥ 多変量関係を 2D で押し付ける
3 変数以上の関係を 2D 散布図で見ようとすると、 色・サイズ・形で代替するが情報量が落ちる。 散布図行列(pairplot)・PCA 後の 2D・3D 散布図・パラレル座標プロットを併用。 高次元の関係を「散布図だけ」で議論しないこと。
⑦ サンプル数を散布図に明記しない
「点が少なく見える」のが本当に少ないのか、 重なっているだけなのか、 タイトル・キャプションに n を明記しないと読者が判断不能。 さらに「データ期間」「集計レベル」「観測単位」も必須情報。 良いプロットには良いキャプションが必要。

🐍 Python 実装バリエーション(scikit-learn / scipy / Optuna)

A. scikit-learn による実装

🎯 解説: ジョイントプロット(散布図 + 周辺ヒストグラム)で 2 変数の同時分布と各々の周辺分布を 1 図に表示。 seaborn.jointplot で簡潔に実装。
📥 入力例: data/raw/SSDSE-B-2026.csv x='A1101', y='B1101' kind='scatter' or 'reg' or 'hex'
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
import numpy as np

# 散布図に非線形回帰曲線を重ねる(多項式)
X = df[['一人当たり県民所得']].values
y = df['持ち家比率'].values

fig, ax = plt.subplots(figsize=(8, 5))
ax.scatter(X, y, alpha=0.6, s=50)

x_grid = np.linspace(X.min(), X.max(), 200).reshape(-1, 1)
for degree, color in [(1, 'red'), (2, 'green'), (3, 'blue')]:
    model = Pipeline([('poly', PolynomialFeatures(degree)), ('lr', LinearRegression())])
    model.fit(X, y)
    ax.plot(x_grid, model.predict(x_grid), color=color, label=f'degree={degree}')

ax.legend(); ax.set_xlabel('県民所得'); ax.set_ylabel('持ち家比率')
plt.savefig('scatter_poly.png', dpi=110)
📤 実行例: 中央: 散布図 上端: x のヒストグラム 右端: y のヒストグラム
💬 読み方: 周辺分布で各変数の歪み・多峰性を確認できる。 kind='hex' は点が多いとき密度を六角形ビンで表示。 kind='kde' でカーネル密度推定。

B. scipy / statsmodels による実装

🎯 解説: クラスタリング付き散布図。 SSDSE-B-2026 を K-means で 3 クラスタに分け、 都市型・地方型・中間型を色分け。 探索的グルーピングの可視化。
📥 入力例: data/raw/SSDSE-B-2026.csv KMeans(n_clusters=3) features: 人口・GDP・高齢化率
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from scipy import stats
from scipy.stats import gaussian_kde
import numpy as np

# 2D カーネル密度推定で散布図を補強
x = df['一人当たり県民所得'].values
y = df['持ち家比率'].values
kde = gaussian_kde(np.vstack([x, y]))

xx, yy = np.mgrid[x.min():x.max():100j, y.min():y.max():100j]
positions = np.vstack([xx.ravel(), yy.ravel()])
zz = kde(positions).reshape(xx.shape)

fig, ax = plt.subplots(figsize=(8, 6))
ax.contourf(xx, yy, zz, levels=10, cmap='Blues', alpha=0.7)
ax.scatter(x, y, c='red', s=20, alpha=0.7, edgecolor='white')

# 相関と回帰
r, p = stats.pearsonr(x, y)
slope, intercept, _, _, _ = stats.linregress(x, y)
xs = np.array([x.min(), x.max()])
ax.plot(xs, intercept + slope * xs, 'k--', label=f'r={r:.2f}, p={p:.3f}')
ax.legend(); plt.savefig('scatter_kde.png', dpi=110)
📤 実行例: 3 色の散布図 クラスタ A(赤): 東京・神奈川・大阪(都市型) クラスタ B(青): 地方 クラスタ C(緑): 中間
💬 読み方: クラスタ数は事前に決める必要あり(エルボー法・シルエット係数で選定)。 K-means は球状クラスタを仮定するため非凸形状には DBSCAN を試す。 標準化必須。

C. Optuna でハイパラ・選択最適化

🎯 解説: 時系列散布図(過去 vs 現在)。 SSDSE-B-2026 で 2020 年と 2024 年の人口を散布図化し、 対角線からのズレで変化方向を確認。
📥 入力例: 過去データ + 現在データ x = 人口(2020) y = 人口(2024)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# LOWESS の bandwidth 最適化(散布図に滑らかな曲線を重ねる)
import statsmodels.api as sm
import optuna

def objective(trial):
    frac = trial.suggest_float('frac', 0.1, 0.9)
    smoothed = sm.nonparametric.lowess(y, x, frac=frac, return_sorted=False)
    return ((y - smoothed)**2).mean()  # MSE 最小化

study = optuna.create_study(direction='minimize')
study.optimize(objective, n_trials=30, show_progress_bar=False)
print('Best frac:', study.best_params)

# 最適 frac で散布図にプロット
best_frac = study.best_params['frac']
smoothed = sm.nonparametric.lowess(y, x, frac=best_frac)
fig, ax = plt.subplots(figsize=(8, 5))
ax.scatter(x, y, alpha=0.6)
ax.plot(smoothed[:, 0], smoothed[:, 1], 'r-', label=f'LOWESS frac={best_frac:.2f}')
ax.legend(); plt.savefig('scatter_lowess.png', dpi=110)
📤 実行例: 散布図 + 対角線(y=x) ほぼ対角上 → 変化少 対角下 → 減少県(多数) 対角上 → 増加県(少数)
💬 読み方: 対角線(y=x)からの距離が変化量。 上下どちら側かで増減の向き。 全県を一度に俯瞰でき、 地方の人口減少が顕著に見える。

D. ライブラリ早見表

ライブラリ / 関数 用途
matplotlib.pyplot.scatter最も柔軟・低レベル
seaborn.scatterplot回帰線・色分けが簡単
seaborn.regplot回帰線+CI 帯
seaborn.jointplotマージナル分布つき散布図
plotly.express.scatterインタラクティブな散布図
matplotlib.hexbin大量データの密度可視化

🎨 直感で掴む — 散布図

散布図は「2 変数の関係を点でプロットする」可視化の王道。 1 点 = 1 観測(県・人・時刻)。 SSDSE-B-2026 で A1101 vs A1303(総人口 vs 高齢人口)を描くと、 ほぼ y=0.27x の直線上に並ぶが、 北海道のように高齢化率が突出して高い県は線の上側にずれて配置される。

💡 学習のコツ:直感で全体像を掴んだら、 次の「📐 定義・数式」で正確な意味を押さえ、 最後に「🧮 実値で計算してみる」で SSDSE-B-2026 の都道府県データを使った計算をなぞるのが効率的です。 比喩は厳密ではないので、 必ず数式と並べて確認してください。

散布図 は「可視化」カテゴリの中核概念。 初めて触れる読者は、 まずこの「🎨 直感」セクションだけ通読し、 必要になった時点で「📐 数式」「🐍 Python」「⚠️ 落とし穴」へ戻る読み方が定着しやすいです。

📐 定義・数式 — 散布図

直感の次は、 厳密な定義を確認します。 数式は言語の一種で、 一度書き慣れれば「言葉より速く伝えられる」便利な道具。 慣れていない方は、 各記号が何を表すかを下の「🔬 記号読み解き」で 1 つずつ確認してください。

【散布図 の中心定義式】
$$ r = \frac{\sum_{i}(x_i-\bar{x})(y_i-\bar{y})}{\sqrt{\sum (x_i-\bar{x})^2 \cdot \sum(y_i-\bar{y})^2}} $$
この式が「散布図」の骨格。 派生形・拡張形はここから生まれる。
📌 読み方のコツ:数式を見たら「左辺は何を定義しているか」「右辺の各項は何の合計・積・比か」を声に出して読み下してみる。 これだけで理解が大きく進みます。

🔬 記号読み解き — 数式を「言葉」に翻訳

上の数式を眺めるだけでは身につかないので、 各記号がどんな役割を担っているかを言葉で押さえます。 「数式を音読する習慣」がつくと、 論文や教科書を読むスピードが体感で 2 倍ほど上がります。

左辺(結果側)
散布図 で定義したい量。 解釈の対象。 単位・スケールを必ず確認する。
右辺(構成要素)
観測できる入力変数(SSDSE-B-2026 でいえば A1101・L3221 など)と推定対象パラメータ(β, σ 等)の組合せ。
添字 i, j, t
i=サンプル(県)、 j=変数、 t=時点。 SSDSE-B-2026 は i ∈ {1..47} 県、 t ∈ {2008..2023}。
和記号 Σ
「足し合わせ」を表す。 添字 i が 1 から n まで動く範囲を明示するのが習慣。
期待値 E[·]、 分散 Var[·]
「ランダム変数の平均」と「ばらつき」。 SSDSE-B-2026 のような集計値でも、 標本誤差・年次変動の文脈で使える。
📚 補足:同じ記号でも分野・教科書によって意味が違うことがあります(例: $\hat{y}$ は予測値だが、 統計の文脈では推定量を意味することも)。 不明確なときは、 必ずその文書の記号定義表を確認しましょう。

🧮 実値で計算してみる — SSDSE-B-2026

数式だけでは「実感」が湧きにくいので、 実データ data/raw/SSDSE-B-2026.csv(47 都道府県 × 16 年)で 1 度手計算してみると理解が定着します。

SSDSE-B-2026 (2023) で A1101 vs A1303 の Pearson 相関は r ≈ 0.997(非常に強い正相関、 人口の多い県ほど高齢人口も多いのは自明)。 ところが「高齢化率=A1303/A1101」を縦軸にすると相関は逆転し、 北海道 33.0%、 秋田県 39.1% などが上方に飛ぶ。 散布図は「軸の取り方で物語が変わる」典型例。

都道府県A1101 総人口A1303 65 歳以上L3221 消費支出
東京都14,086,0003,205,000341,320
神奈川県9,229,0002,390,000306,565
大阪府8,763,0002,424,000271,246
愛知県7,477,0001,923,000300,221
埼玉県7,331,0002,012,000344,092
千葉県6,257,0001,756,000306,943

上記は SSDSE-B-2026 (2023) からの抜粋。 手計算で確認した値が、 後述の Python 実装で得る値と一致することを確認すると、 「数式とコードの対応関係」がクリアに見えるようになります。

🐍 Python 実装 — 散布図

公的統計(SSDSE-B-2026)を題材に、 最小限の Python コードで 散布図 を動作させます。 まずはこのまま実行してみてください。

# 散布図 を SSDSE-B-2026 で実行する最小コード
import pandas as pd
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]  # 2023 年のみ抽出
print(df.shape)  # (47, 112)
print(df[['Prefecture','A1101','A1303','L3221']].head())

import matplotlib.pyplot as plt
fig, axes = plt.subplots(1,2, figsize=(12,5))
axes[0].scatter(df['A1101'], df['A1303'], alpha=0.7)
axes[0].set_xlabel('A1101 総人口'); axes[0].set_ylabel('A1303 65歳以上')
axes[0].set_title('総人口 vs 高齢人口')
axes[1].scatter(df['A1101'], df['A1303']/df['A1101'], alpha=0.7, color='red')
axes[1].set_xlabel('A1101 総人口'); axes[1].set_ylabel('高齢化率')
axes[1].set_title('総人口 vs 高齢化率')
plt.tight_layout(); plt.savefig('scatter_demo.png', dpi=100)
print('r1:', df[['A1101','A1303']].corr().iloc[0,1])

上のコードで動かない場合は、 ①必要なパッケージがインストール済みか(pip install pandas scikit-learn scipy statsmodels matplotlib)、 ②データファイルが data/raw/SSDSE-B-2026.csv に存在するか、 ③encoding='cp932' になっているかを確認してください。

⚠️ よくある落とし穴 — 散布図

散布図 を使うときに初学者が踏みやすい失敗パターン。 1 度経験してしまえば次から避けられますが、 先に知っておくに越したことはありません。

❌ Overplotting で点が重なる
n が大きいと黒い塊になる。 alpha・jitter・hexbin・2D KDE を使う。
❌ 軸が片対数か両対数か明示しない
人口・所得は対数軸が自然。 タイトル/ラベルに「log」を必ず入れる。
❌ 外れ値 1 点で関係が見えなくなる
東京都を除くと残り 46 県の構造が見える。 サブセット散布図も併用。
🛡 防御策まとめ:「適用条件を確認する」「結果と前提をセットで記述する」「不確実性を必ず併記する」の 3 点を習慣化すれば、 上記の罠の大半は回避できます。