このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
英語教育における都市部とへき地の格差は、単なる学習機会の差にとどまらず、将来のキャリア・賃金格差にも繋がる深刻な問題である。本研究は、都道府県別の統計データを用いて「英語能力と経済格差の関係」を定量的に分析し、格差是正の政策を提案する。
まず「都市部とへき地の生徒間の英語能力の格差を是正するためには」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
相関分析 単回帰分析 決定係数R² 教科間比較
| データ | 出典 | 変数 |
|---|---|---|
| 全国学力・学習状況調査 | 国立教育政策研究所 | 都道府県別 英語・国語・数学 平均正答率 |
| 賃金構造基本統計調査 | 厚生労働省 | 都道府県別平均所得(万円/年) |
| SSDSE-D(社会生活) | 統計数理研究所 | 週あたり学業時間(時間) |
| SSDSE(社会生活) | 統計数理研究所 | 英語活動行動者率(%) |
| 種別 | 変数名 | 単位 | 想定効果 |
|---|---|---|---|
| 目的変数 | 英語平均正答率 | % | — |
| 説明変数 | 都道府県別平均所得 | 万円/年 | 正(経済的余裕 → 英語投資) |
| 週あたり学業時間 | 時間 | 正?(要確認) | |
| 英語活動行動者率 | % | 正(英語接触機会) | |
| ICT活用割合 | % | 正(オンライン学習) |
本教育用コードは合成データを使用(np.random.seed(42))。実際の分析は国立教育政策研究所の実データによる。
1 2 3 4 5 6 7 8 9 10 11 12 | df_b = pd.read_csv( 'data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1 ) df_b = df_b[df_b['地域コード'].str.match(r'^R\d{5}$', na=False)] df_2022 = df_b[df_b['年度'] == 2022].copy().reset_index(drop=True) for col in ['総人口', '65歳以上人口', '高等学校卒業者数', '高等学校卒業者のうち進学者数', '教育費(二人以上の世帯)', '保育所等数', '年平均気温', 'ごみのリサイクル率', '婚姻件数']: df_2022[col] = pd.to_numeric(df_2022[col], errors='coerce') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。df['地域コード'].str.match(r'^R\d{5}', ...) — 正規表現で「R+数字5桁」の行(47都道府県)だけTrueにし、真偽値で行をフィルタ。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。13 14 15 16 17 18 19 20 21 | df_e_raw = pd.read_csv( 'data/raw/SSDSE-E-2026.csv', encoding='cp932', header=0 ) df_e = df_e_raw.iloc[1:].copy(); df_e.columns = df_e_raw.iloc[0].values df_e2 = df_e.iloc[1:].copy(); df_e2.columns = df_e.iloc[0].values df_e2 = df_e2[df_e2['都道府県'] != '全国'].reset_index(drop=True) df_e2['1人当たり県民所得(平成27年基準)'] = pd.to_numeric( df_e2['1人当たり県民所得(平成27年基準)'], errors='coerce') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。22 23 24 25 26 27 | df_2022['都道府県_key'] = df_2022['都道府県'].str.replace('県$|府$|都$|道$', '', regex=True) df_e2['都道府県_key'] = df_e2['都道府県'].str.replace('県$|府$|都$|道$', '', regex=True) df = df_2022.merge( df_e2[['都道府県_key', '1人当たり県民所得(平成27年基準)']], on='都道府県_key', how='left' ) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。28 29 30 31 32 33 34 35 36 37 | # 目的変数: 大学進学率 (%) df['大学進学率'] = df['高等学校卒業者のうち進学者数'] / df['高等学校卒業者数'] * 100 # 説明変数 df['高齢化率'] = df['65歳以上人口'] / df['総人口'] * 100 df['保育所充実度'] = df['保育所等数'] / df['総人口'] * 1000 df['ln所得'] = np.log(df['1人当たり県民所得(平成27年基準)']) df['ln人口密度'] = np.log( df['総人口'] / (df_2022['総人口'] / df_2022['総人口']) # dummy placeholder ) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。38 39 40 41 42 43 44 45 46 | # 都道府県名(表示用) PREFS = df['都道府県'].tolist() # 有効行のみ抽出 cols_needed = ['大学進学率', 'ln所得', '教育費(二人以上の世帯)', '保育所充実度', '年平均気温', '高齢化率', '1人当たり県民所得(平成27年基準)'] df_ana = df[cols_needed + ['都道府県']].dropna().reset_index(drop=True) N = len(df_ana) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | # 配列として取り出す y = df_ana['大学進学率'].values ln_income = df_ana['ln所得'].values edu_exp = df_ana['教育費(二人以上の世帯)'].values childcare = df_ana['保育所充実度'].values temperature = df_ana['年平均気温'].values aging = df_ana['高齢化率'].values income_raw = df_ana['1人当たり県民所得(平成27年基準)'].values prefs = df_ana['都道府県'].tolist() print("=" * 60) print(f"■ データ概要: N={N}都道府県(SSDSE-B 2022 / SSDSE-E)") print("=" * 60) print(df_ana[['大学進学率', '1人当たり県民所得(平成27年基準)', '教育費(二人以上の世帯)', '保育所充実度', '年平均気温', '高齢化率']].describe().round(2)) |
============================================================
■ データ概要: N=47都道府県(SSDSE-B 2022 / SSDSE-E)
============================================================
大学進学率 1人当たり県民所得(平成27年基準) 教育費(二人以上の世帯) 保育所充実度 年平均気温 高齢化率
count 47.00 47.00 47.00 47.00 47.00 47.00
mean 56.62 2995.94 10645.77 0.28 16.07 31.35
std 7.01 496.98 4337.37 0.07 2.29 3.27
min 46.20 2258.00 5540.00 0.17 10.20 22.81
25% 50.76 2743.50 7760.50 0.22 15.25 29.85
50% 56.77 2949.00 9788.00 0.24 16.40 31.42
75% 61.33 3170.00 11796.50 0.33 17.35 33.72
max 72.99 5761.00 27959.00 0.45 23.70 38.60.describe() — 件数・平均・標準偏差・四分位・最大/最小を一括計算。データの素性チェックに必須。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | REGION_MAP = { '北海道': '北海道', '青森県': '東北', '岩手県': '東北', '宮城県': '東北', '秋田県': '東北', '山形県': '東北', '福島県': '東北', '茨城県': '関東', '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東', '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部', '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部', '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿', '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿', '鳥取県': '中国', '島根県': '中国', '岡山県': '中国', '広島県': '中国', '山口県': '中国', '徳島県': '四国', '香川県': '四国', '愛媛県': '四国', '高知県': '四国', '福岡県': '九州', '佐賀県': '九州', '長崎県': '九州', '熊本県': '九州', '大分県': '九州', '宮崎県': '九州', '鹿児島県': '九州', '沖縄県': '九州', } df_ana['地域'] = df_ana['都道府県'].map(REGION_MAP) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。英語・国語・数学の各正答率と都道府県別平均所得のピアソン相関係数を算出し、教科間の「経済依存度」の差を比較する。
| 教科 | 相関係数 r | p値 | 判定 | 解釈 |
|---|---|---|---|---|
| 英語 | ≈ 0.76 | p < 0.001 | ***(有意) | 所得格差の影響が最大 |
| 数学 | ≈ 0.51 | p < 0.05 | *(有意) | 中程度の経済依存 |
| 国語 | ≈ 0.19 | n.s. | 非有意 | 経済格差の影響は小さい |
相関係数 r の大きさを解釈する際は「効果量」の基準を参照する。N=47(都道府県数)では検出力が低いため、小さな相関は有意にならない。
79 80 81 82 83 84 85 86 87 88 89 90 91 | fig1, ax1 = plt.subplots(figsize=(8, 6)) ax1.scatter(ln_income, y, color='#1565C0', s=55, alpha=0.7, zorder=3, label='各都道府県') # 東京・沖縄・愛知をハイライト highlights = {'東京都': None, '沖縄県': None, '愛知県': None, '青森県': None} for pref, (xi, yi) in { p: (ln_income[i], y[i]) for i, p in enumerate(prefs) if p in highlights }.items(): ax1.scatter(xi, yi, color='#C62828', s=100, zorder=5) ax1.annotate(pref.replace('都', '').replace('府', '').replace('県', ''), (xi, yi), textcoords='offset points', xytext=(5, 4), fontsize=8.5, color='#C62828') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | # 回帰直線 xs = np.linspace(ln_income.min() - 0.05, ln_income.max() + 0.05, 200) slope = model_simple.params[1] intercept = model_simple.params[0] ax1.plot(xs, intercept + slope * xs, 'r-', linewidth=2, alpha=0.8, label=f'回帰直線 (R²={model_simple.rsquared:.3f})') pred = model_simple.get_prediction(sm.add_constant(xs)) ci = pred.conf_int(alpha=0.05) ax1.fill_between(xs, ci[:, 0], ci[:, 1], alpha=0.12, color='red', label='95%信頼区間') r1, p1 = stats.pearsonr(ln_income, y) ax1.set_xlabel('ln(1人当たり県民所得) [千円, 平成27年基準]', fontsize=11) ax1.set_ylabel('大学進学率(%)', fontsize=11) ax1.set_title(f'1人当たり県民所得(対数)と大学進学率\nr={r1:.3f}, p={p1:.4f}', fontsize=12, fontweight='bold') ax1.legend(fontsize=9) ax1.grid(True, alpha=0.3) plt.tight_layout() fig1.savefig(os.path.join(FIG_DIR, '2024_H5_2_fig1_scatter_income.png'), bbox_inches='tight', dpi=150) plt.close(fig1) print("\n図1保存: 2024_H5_2_fig1_scatter_income.png") |
図1保存: 2024_H5_2_fig1_scatter_income.png
ax.fill_between(...) — 2つの曲線で囲まれた領域を塗りつぶし。Lorenz曲線の格差面積などを可視化。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。平均所得を説明変数、英語正答率を目的変数とした単回帰分析を行い、決定係数(R²)で当てはまりの良さを評価する。
statsmodels で OLS(最小二乗法)を実行し、回帰係数・p値・R² を一括取得する方法を示す。
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | fig2, ax2 = plt.subplots(figsize=(8, 6)) ax2.scatter(edu_exp, y, color='#2E7D32', s=55, alpha=0.7, zorder=3, label='各都道府県') for pref, (xi, yi) in { p: (edu_exp[i], y[i]) for i, p in enumerate(prefs) if p in highlights }.items(): ax2.scatter(xi, yi, color='#C62828', s=80, zorder=5) ax2.annotate(pref.replace('都', '').replace('府', '').replace('県', ''), (xi, yi), textcoords='offset points', xytext=(5, 4), fontsize=8.5, color='#C62828') z2 = np.polyfit(edu_exp, y, 1) xs2 = np.linspace(edu_exp.min() - 1000, edu_exp.max() + 1000, 200) ax2.plot(xs2, np.poly1d(z2)(xs2), color='#2E7D32', linewidth=2, alpha=0.8, label=f'回帰直線') r2, p2 = stats.pearsonr(edu_exp, y) ax2.set_xlabel('教育費(二人以上の世帯)[円]', fontsize=11) ax2.set_ylabel('大学進学率(%)', fontsize=11) ax2.set_title(f'教育費と大学進学率\nr={r2:.3f}, p={p2:.4f}', fontsize=12, fontweight='bold') ax2.legend(fontsize=9) ax2.grid(True, alpha=0.3) plt.tight_layout() fig2.savefig(os.path.join(FIG_DIR, '2024_H5_2_fig2_scatter_edu.png'), bbox_inches='tight', dpi=150) plt.close(fig2) print("図2保存: 2024_H5_2_fig2_scatter_edu.png") |
図2保存: 2024_H5_2_fig2_scatter_edu.png
fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。同じ分析を国語正答率に対して行い、英語と国語で「所得との関係」がどれほど異なるかを視覚的に確認する。
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | from sklearn.preprocessing import StandardScaler fig3, ax3 = plt.subplots(figsize=(8, 5)) X2_mat = np.column_stack([ln_income, edu_exp, childcare, temperature, aging]) scaler = StandardScaler() X2_std = scaler.fit_transform(X2_mat) y_std = (y - y.mean()) / y.std() model_std = sm.OLS(y_std, sm.add_constant(X2_std)).fit() var_labels = ['ln(県民所得)', '教育費', '保育所充実度', '年平均気温', '高齢化率'] coefs = model_std.params[1:] pvals = model_std.pvalues[1:] ses = model_std.bse[1:] y_pos = np.arange(len(var_labels)) cols = ['#C62828' if c > 0 else '#1565C0' for c in coefs] ax3.barh(y_pos, coefs, color=cols, alpha=0.75, edgecolor='white', height=0.55) ax3.errorbar(coefs, y_pos, xerr=1.96 * ses, fmt='none', color='#333', capsize=4, linewidth=1.2) ax3.axvline(0, color='gray', linestyle='--', linewidth=1.0) ax3.set_yticks(y_pos) ax3.set_yticklabels(var_labels, fontsize=10) ax3.set_xlabel('標準化回帰係数 β(±1.96SE)', fontsize=11) ax3.set_title(f'重回帰モデルの標準化係数\nR²={model_multi.rsquared:.3f}', fontsize=12, fontweight='bold') ax3.invert_yaxis() ax3.grid(axis='x', alpha=0.3) for i, (c, p) in enumerate(zip(coefs, pvals)): sig = '***' if p < 0.001 else '**' if p < 0.01 else '*' if p < 0.05 else 'n.s.' offset = 0.01 if c >= 0 else -0.01 ha = 'left' if c >= 0 else 'right' ax3.text(c + offset, i, sig, va='center', ha=ha, fontsize=9, color='#333') from matplotlib.patches import Patch ax3.legend(handles=[Patch(color='#C62828', alpha=0.75, label='正の効果'), Patch(color='#1565C0', alpha=0.75, label='負の効果')], fontsize=9) plt.tight_layout() fig3.savefig(os.path.join(FIG_DIR, '2024_H5_2_fig3_coef.png'), bbox_inches='tight', dpi=150) plt.close(fig3) print("図3保存: 2024_H5_2_fig3_coef.png") |
図3保存: 2024_H5_2_fig3_coef.png
import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。StandardScaler().fit_transform(X) — 各列を「平均0・分散1」に標準化。単位が違う変数のβを比較可能に。sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。plt.subplots(figsize=(W, H)) で図サイズ指定、fig.savefig(..., bbox_inches='tight') で余白を自動で詰めて保存。「たくさん勉強すれば英語が伸びる」という仮説を検証する。学業時間が多い都道府県ほど英語正答率が高いかを相関分析で確認した。
「相関なし(r=0)」という帰無仮説を t 検定で検証する。N=47 では r≥0.29 程度で p<0.05 になる。
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | import numpy as np import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from scipy import stats import statsmodels.api as sm import warnings warnings.filterwarnings('ignore') plt.rcParams['font.family'] = 'Hiragino Sans' plt.rcParams['axes.unicode_minus'] = False plt.rcParams['figure.dpi'] = 150 import os FIG_DIR = 'html/figures' os.makedirs(FIG_DIR, exist_ok=True) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。matplotlib.use('Agg') — グラフを画面表示せずファイルに保存するためのおまじない。plt.rcParams['font.family'] — グラフの日本語表示用フォント指定(Macは Hiragino Sans、Windowsなら Yu Gothic 等)。os.makedirs('html/figures', exist_ok=True) — 図の保存先フォルダを作る(既にあってもOK)。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。205 206 207 208 209 210 | print("\n" + "=" * 60) print("■ Step1. 単回帰: 大学進学率 ~ ln(1人当たり県民所得)") print("=" * 60) X1 = sm.add_constant(ln_income) model_simple = sm.OLS(y, X1).fit() print(model_simple.summary2()) |
============================================================
■ Step1. 単回帰: 大学進学率 ~ ln(1人当たり県民所得)
============================================================
Results: Ordinary least squares
=================================================================
Model: OLS Adj. R-squared: 0.359
Dependent Variable: y AIC: 297.4340
Date: 2026-05-18 11:24 BIC: 301.1343
No. Observations: 47 Log-Likelihood: -146.72
Df Model: 1 F-statistic: 26.76
Df Residuals: 45 Prob (F-statistic): 5.16e-06
R-squared: 0.373 Scale: 31.465
------------------------------------------------------------------
Coef. Std.Err. t P>|t| [0.025 0.975]
------------------------------------------------------------------
const -191.5294 47.9794 -3.9919 0.0002 -288.1650 -94.8938
x1 31.0398 6.0006 5.1728 0.0000 18.9540 43.1256
-----------------------------------------------------------------
Omnibus: 5.511 Durbin-Watson: 1.263
Prob(Omnibus): 0.064 Jarque-Bera (JB): 4.748
Skew: 0.772 Prob(JB): 0.093
Kurtosis: 3.195 Condition No.: 476
=================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the
errors is correctly specified.sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。211 212 213 214 215 216 217 218 | print("\n" + "=" * 60) print("■ Step2. 重回帰(多変数モデル)") print("=" * 60) X2 = sm.add_constant( np.column_stack([ln_income, edu_exp, childcare, temperature, aging]) ) model_multi = sm.OLS(y, X2).fit() print(model_multi.summary2()) |
============================================================
■ Step2. 重回帰(多変数モデル)
============================================================
Results: Ordinary least squares
=================================================================
Model: OLS Adj. R-squared: 0.551
Dependent Variable: y AIC: 284.2718
Date: 2026-05-18 11:24 BIC: 295.3726
No. Observations: 47 Log-Likelihood: -136.14
Df Model: 5 F-statistic: 12.31
Df Residuals: 41 Prob (F-statistic): 2.55e-07
R-squared: 0.600 Scale: 22.015
------------------------------------------------------------------
Coef. Std.Err. t P>|t| [0.025 0.975]
------------------------------------------------------------------
const -74.3038 57.2050 -1.2989 0.2012 -189.8317 41.2242
x1 18.6633 6.2917 2.9663 0.0050 5.9569 31.3696
x2 0.0001 0.0002 0.5321 0.5976 -0.0003 0.0005
x3 -33.7978 11.1160 -3.0405 0.0041 -56.2470 -11.3486
x4 0.3292 0.3627 0.9075 0.3694 -0.4034 1.0618
x5 -0.4905 0.3015 -1.6270 0.1114 -1.0994 0.1184
-----------------------------------------------------------------
Omnibus: 1.700 Durbin-Watson: 1.334
Prob(Omnibus): 0.427 Jarque-Bera (JB): 1.294
Skew: 0.406 Prob(JB): 0.524
Kurtosis: 2.978 Condition No.: 965111
=================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the
errors is correctly specified.
[2] The condition number is large, 9.65e+05. This might indicate
that there are strong multicollinearity or other numerical
problems.sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | print("\n" + "=" * 60) print("■ Step3. Pearson相関(大学進学率との相関)") print("=" * 60) var_list = { 'ln(1人当たり県民所得)': ln_income, '教育費': edu_exp, '保育所充実度': childcare, '年平均気温': temperature, '高齢化率': aging, } print(f"\n {'変数':<22} {'r':>8} {'p値':>10} {'有意':>6}") print(" " + "-" * 50) for name, x in var_list.items(): r, p = stats.pearsonr(x, y) sig = '***' if p < 0.001 else '**' if p < 0.01 else '*' if p < 0.05 else 'n.s.' print(f" {name:<22} {r:>8.4f} {p:>10.4f} {sig:>6}") |
============================================================ ■ Step3. Pearson相関(大学進学率との相関) ============================================================ 変数 r p値 有意 -------------------------------------------------- ln(1人当たり県民所得) 0.6106 0.0000 *** 教育費 0.4945 0.0004 *** 保育所充実度 -0.5692 0.0000 *** 年平均気温 0.1061 0.4776 n.s. 高齢化率 -0.5879 0.0000 ***
stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | fig4, ax4 = plt.subplots(figsize=(9, 5.5)) region_mean = df_ana.groupby('地域')['大学進学率'].mean().sort_values(ascending=False) region_std = df_ana.groupby('地域')['大学進学率'].std() region_order = region_mean.index.tolist() region_colors = { '関東': '#C62828', '近畿': '#E65100', '中部': '#1565C0', '北海道': '#2E7D32', '東北': '#6A1B9A', '中国': '#00838F', '四国': '#558B2F', '九州': '#4527A0', } bar_colors = [region_colors.get(r, '#888888') for r in region_order] bars = ax4.bar(region_order, region_mean[region_order], color=bar_colors, alpha=0.78, edgecolor='white', width=0.6) ax4.errorbar(range(len(region_order)), region_mean[region_order], yerr=region_std[region_order], fmt='none', color='#333', capsize=5, linewidth=1.3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。.dropna() は欠損行を除去、.copy() は独立したコピーを作る。pandasで警告を防ぐ定石。252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | # 全国平均線 national_mean = y.mean() ax4.axhline(national_mean, color='gray', linestyle='--', linewidth=1.5, label=f'全国平均 {national_mean:.1f}%') for i, (r, v) in enumerate(zip(region_order, region_mean[region_order])): ax4.text(i, v + 0.5, f'{v:.1f}', ha='center', va='bottom', fontsize=9, fontweight='bold') ax4.set_ylabel('大学進学率(%)', fontsize=11) ax4.set_title('地域別 大学進学率の比較(8地域区分)\n(SSDSE-B 2022, 棒:平均, エラーバー:SD)', fontsize=12, fontweight='bold') ax4.legend(fontsize=9) ax4.grid(axis='y', alpha=0.3) ax4.tick_params(axis='x', labelsize=10) plt.tight_layout() fig4.savefig(os.path.join(FIG_DIR, '2024_H5_2_fig4_region.png'), bbox_inches='tight', dpi=150) plt.close(fig4) print("図4保存: 2024_H5_2_fig4_region.png") print("\n全図の生成完了(4枚)") |
図4保存: 2024_H5_2_fig4_region.png 全図の生成完了(4枚)
ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。| データ | 出典 |
|---|---|
| 全国学力・学習状況調査(都道府県別正答率) | 国立教育政策研究所 |
| 賃金構造基本統計調査 | 厚生労働省 |
| SSDSE-D(社会生活:学業時間等) | 統計数理研究所 |
| SSDSE(英語活動行動者率) | 統計数理研究所 |
本教育用コードは合成データを使用(np.random.seed(42))。実際の分析は国立教育政策研究所の実データによる。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。