このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
日本の食料自給率(カロリーベース)は長期的に低下を続け、2022年度は38%(農林水産省調べ)にとどまる。食料安全保障の観点から、日本が食料を海外に依存している現状の構造を統計データで解明し、自給率向上のための政策的示唆を得ることが本研究の目的である。
まず「日本の食料自給率を上げるために」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
SSDSE-B 時系列分析 相関分析 重回帰分析 代理変数
SSDSE(社会・人口統計体系データセット)-B は都道府県レベルの統計データを収録する。2012〜2023年の12年分・47都道府県のパネルデータ(計564行)を使用した。
| 変数 | SSDSE-Bコード | 説明 | 役割 |
|---|---|---|---|
| 食料費割合(目的変数) | L322101 / L3221 × 100 | 食料費 / 消費支出(二人以上世帯) | 食料依存度の代理変数 |
| 消費支出 | L3221 | 二人以上世帯の月間消費支出(円) | 所得・生活水準の指標 |
| 住宅地価格 | C5401 | 住宅地平均価格(円/m²) | 都市化・地価の指標 |
| 高齢化率 | A1303 / A1101 × 100 | 65歳以上人口割合(%) | 高齢化の指標 |
| 年平均気温 | B4101 | 年平均気温(℃) | 農業・気候条件の指標 |
| 年間降水量 | B4109 | 年間降水量(mm) | 農業・気候条件の指標 |
| 転出率 | A5102 / A1101 × 100 | 転出者数 / 総人口(%) | 農村過疎化の指標 |
分析したい指標が直接入手できない場合、理論的に関連が深い別の指標で代替する手法を「代理変数」という。重要なのは (1) 代理変数と真の指標の関係を明示すること、(2) 代理変数固有のバイアスを認識することの2点。
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 | df_raw = pd.read_csv( os.path.join(DATA_DIR, 'SSDSE-B-2026.csv'), encoding='cp932', header=0 ) # 都道府県コード(R01000〜R47000)の行のみ抽出 pref_mask = df_raw['Code'].str.match(r'^R\d{5}$', na=False) df_pref = df_raw[pref_mask].copy().reset_index(drop=True) year_col = df_pref.columns[0] # 'SSDSE-B-2026' df_pref[year_col] = pd.to_numeric(df_pref[year_col], errors='coerce') # 数値変換 num_cols = ['L3221', 'L322101', 'L322108', 'L322109', 'A1101', 'A1303', 'A5102', 'L3221', 'C5401', 'B4101', 'B4109'] for c in num_cols: if c in df_pref.columns: df_pref[c] = pd.to_numeric(df_pref[c], errors='coerce') print("=" * 60) print("■ SSDSE-B 都道府県データ読み込み完了") print(f" 全行数: {len(df_pref)}(47都道府県 × 12年)") print(f" 年度: {sorted(df_pref[year_col].dropna().astype(int).unique())}") print("=" * 60) |
============================================================ ■ SSDSE-B 都道府県データ読み込み完了 全行数: 564(47都道府県 × 12年) 年度: [np.int64(2012), np.int64(2013), np.int64(2014), np.int64(2015), np.int64(2016), np.int64(2017), np.int64(2018), np.int64(2019), np.int64(2020), np.int64(2021), np.int64(2022), np.int64(2023)] ============================================================
pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。df['地域コード'].str.match(r'^R\d{5}', ...) — 正規表現で「R+数字5桁」の行(47都道府県)だけTrueにし、真偽値で行をフィルタ。.astype(int) — 列を整数に変換(年度などを数値比較するため)。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。2012〜2023年の47都道府県平均値を用いて、消費支出内の食料費・教育費・教養娯楽費の割合の推移を分析する。
| 変数 | 2012年 | 2023年 | 変化 | r(年との相関) | p値 | 有意 |
|---|---|---|---|---|---|---|
| 食料費割合 | 23.3% | 27.2% | +3.9ポイント↑ | r=0.961 | p<0.001 | *** |
| 教育費割合 | 4.0% | 3.2% | −0.7ポイント↓ | r=−0.660 | p=0.020 | * |
| 教養娯楽費割合 | 9.7% | 9.3% | −0.3ポイント↓ | r=−0.737 | p=0.006 | ** |
時系列データのトレンドを検定する方法は複数ある。単純なピアソン相関(年との相関)は線形トレンドの有無を示すが、データが独立でない点(系列相関)に注意が必要。
27 28 29 30 31 32 33 34 35 36 37 38 | fig1, ax1 = plt.subplots(figsize=(10, 5)) years_plot = ts.index.astype(int) ax1.plot(years_plot, ts['food_pct'].values, 'o-', color='#C62828', linewidth=2.2, markersize=6, label='食料費割合(%)') ax1.plot(years_plot, ts['edu_pct'].values, 's--', color='#1565C0', linewidth=1.8, markersize=5, label='教育費割合(%)') ax1.plot(years_plot, ts['ent_pct'].values, '^:', color='#2E7D32', linewidth=1.8, markersize=5, label='教養娯楽費割合(%)') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.astype(int) — 列を整数に変換(年度などを数値比較するため)。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | # コロナ禍の影響を示す帯 ax1.axvspan(2020, 2021, alpha=0.08, color='gray', label='コロナ禍 (2020-2021)') # 近似直線(食料費) z1 = np.polyfit(years_arr, ts['food_pct'].values, 1) ax1.plot(years_plot, np.poly1d(z1)(years_arr), '--', color='#C62828', alpha=0.45, linewidth=1.2) ax1.set_xlabel('年度', fontsize=12) ax1.set_ylabel('消費支出に占める割合(%)', fontsize=12) ax1.set_title('消費支出内訳の時系列推移(2012〜2023年 全国都道府県平均)\n' '食料費割合の上昇傾向に注目', fontsize=12, fontweight='bold') ax1.set_xticks(years_plot) ax1.set_xticklabels([str(y) for y in years_plot], rotation=45, fontsize=9) ax1.legend(fontsize=10, loc='upper left') ax1.grid(True, alpha=0.35) ax1.annotate(f'r={r_food:.3f}\n(p={p_food:.3f})', xy=(2020, ts.loc[2020, 'food_pct']), xytext=(2017.5, ts['food_pct'].max() - 0.3), fontsize=9, color='#C62828', arrowprops=dict(arrowstyle='->', color='#C62828', alpha=0.6)) plt.tight_layout() fig1.savefig(os.path.join(FIG_DIR, '2023_H5_5_fig1_ts.png'), bbox_inches='tight', dpi=150) plt.close(fig1) print("\n図1保存: 2023_H5_5_fig1_ts.png") |
図1保存: 2023_H5_5_fig1_ts.png
x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。2022年の47都道府県横断面データを用い、食料費割合と各地域特性変数の相関を分析する。N=47と小サンプルであるため、相関係数の解釈は効果量(Cohen's r)も参考にする。
| 説明変数 | r | p値 | 有意 | 解釈 |
|---|---|---|---|---|
| 住宅地価格 | 0.345 | 0.018 | * | 都市部ほど食料費割合が高い(外食・高価格食品) |
| 消費支出 | −0.281 | 0.056 | n.s. | 所得が高い地域ほど食料費比率が低め(他支出も多い) |
| 転出率 | 0.207 | 0.163 | n.s. | 人口流出地域で食料費割合がやや高い |
| 高齢化率 | −0.241 | 0.103 | n.s. | 高齢化が進む地域ほど食料費割合がやや低い |
| 気温 | −0.145 | 0.333 | n.s. | 気温との関係は弱い(気候の食料費への影響は限定的) |
| 降水量 | 0.100 | 0.505 | n.s. | 有意な相関なし |
67 68 69 70 71 72 | fig2, ax2 = plt.subplots(figsize=(9, 6)) temp_vals = X_raw[:, VAR_NAMES.index('気温')] r_t, p_t = stats.pearsonr(temp_vals, y_vals) ax2.scatter(temp_vals, y_vals, color='#1565C0', s=55, alpha=0.65, zorder=3, label='都道府県') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | # 回帰直線 z2 = np.polyfit(temp_vals, y_vals, 1) xs2 = np.linspace(temp_vals.min(), temp_vals.max(), 100) ax2.plot(xs2, np.poly1d(z2)(xs2), 'r-', linewidth=1.8, alpha=0.75, label=f'近似直線 r={r_t:.3f}') # 代表都道府県にラベル highlight = {'北海道': '#C62828', '東京都': '#2E7D32', '沖縄県': '#FF8F00', '青森県': '#6A1B9A', '大阪府': '#1565C0'} for i, pname in enumerate(pref_names): if pname in highlight: ax2.annotate(pname, xy=(temp_vals[i], y_vals[i]), xytext=(temp_vals[i] + 0.3, y_vals[i] + 0.05), fontsize=9, color=highlight[pname], arrowprops=dict(arrowstyle='->', color=highlight[pname], alpha=0.7)) ax2.scatter([temp_vals[i]], [y_vals[i]], color=highlight[pname], s=90, zorder=5) ax2.set_xlabel('年平均気温(℃)', fontsize=12) ax2.set_ylabel('食料費割合(食料費 / 消費支出 × 100, %)', fontsize=12) ax2.set_title(f'気温と食料費割合の関係(2022年 N={N}都道府県)\n' f'気候条件と食消費の地域差', fontsize=12, fontweight='bold') ax2.legend(fontsize=10) ax2.grid(True, alpha=0.3) sig_text = f'r={r_t:.4f}, p={p_t:.4f}' sig_text += ' (***)' if p_t < 0.001 else ' (**)' if p_t < 0.01 else ' (*)' if p_t < 0.05 else ' (n.s.)' ax2.text(0.98, 0.04, sig_text, transform=ax2.transAxes, ha='right', fontsize=9.5, color='#333', bbox=dict(boxstyle='round,pad=0.3', facecolor='#FFF9C4', edgecolor='#F9A825', alpha=0.8)) plt.tight_layout() fig2.savefig(os.path.join(FIG_DIR, '2023_H5_5_fig2_temp.png'), bbox_inches='tight', dpi=150) plt.close(fig2) print("図2保存: 2023_H5_5_fig2_temp.png") |
図2保存: 2023_H5_5_fig2_temp.png
df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。有意な相関が確認された変数を含む全変数投入の重回帰モデルを推定する。目的変数は食料費割合(%)、説明変数は6変数(N=47都道府県)。
| 変数 | 回帰係数 | 標準誤差 | t値 | p値 | 有意 |
|---|---|---|---|---|---|
| 定数項 | 45.63 | 4.84 | 9.42 | 0.000 | *** |
| 高齢化率 | −0.141 | 0.075 | −1.878 | 0.068 | n.s. |
| 消費支出 | −0.000018 | 0.000004 | −4.438 | 0.000 | *** |
| 住宅地価格 | +0.000011 | 0.000006 | 1.906 | 0.064 | n.s. |
| 気温 | −0.301 | 0.087 | −3.457 | 0.001 | ** |
| 降水量 | +0.0005 | 0.0003 | 1.683 | 0.100 | n.s. |
| 転出率 | +0.513 | 0.840 | 0.611 | 0.544 | n.s. |
都道府県データ(N=47)で多変数の重回帰を行う場合、自由度が小さくなり推定が不安定になりやすい。一般に「変数1つあたりサンプル数10〜20以上」が目安。6変数ならN≥60〜120が望ましい。N=47では過学習リスクがあり、調整R²で評価することが重要。
110 111 112 113 114 115 116 117 118 119 120 | fig3, ax3 = plt.subplots(figsize=(9, 6)) land_vals = X_raw[:, VAR_NAMES.index('住宅地価格')] r_l, p_l = stats.pearsonr(land_vals, y_vals) ax3.scatter(land_vals / 1000, y_vals, color='#E65100', s=55, alpha=0.65, zorder=3, label='都道府県') z3 = np.polyfit(land_vals, y_vals, 1) xs3_raw = np.linspace(land_vals.min(), land_vals.max(), 100) ax3.plot(xs3_raw / 1000, np.poly1d(z3)(xs3_raw), 'r-', linewidth=1.8, alpha=0.75, label=f'近似直線 r={r_l:.3f}') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | # 代表都道府県ラベル highlight2 = {'東京都': '#C62828', '大阪府': '#1565C0', '沖縄県': '#FF8F00', '北海道': '#2E7D32', '秋田県': '#6A1B9A'} for i, pname in enumerate(pref_names): if pname in highlight2: ax3.annotate(pname, xy=(land_vals[i] / 1000, y_vals[i]), xytext=(land_vals[i] / 1000 + 5, y_vals[i] + 0.1), fontsize=9, color=highlight2[pname], arrowprops=dict(arrowstyle='->', color=highlight2[pname], alpha=0.7)) ax3.scatter([land_vals[i] / 1000], [y_vals[i]], color=highlight2[pname], s=90, zorder=5) ax3.set_xlabel('住宅地平均価格(千円/m²)', fontsize=12) ax3.set_ylabel('食料費割合(食料費 / 消費支出 × 100, %)', fontsize=12) ax3.set_title(f'住宅地価格と食料費割合の関係(2022年 N={N}都道府県)\n' f'都市部・農村部での食消費パターンの違い', fontsize=12, fontweight='bold') ax3.legend(fontsize=10) ax3.grid(True, alpha=0.3) sig_text3 = f'r={r_l:.4f}, p={p_l:.4f}' sig_text3 += ' (***)' if p_l < 0.001 else ' (**)' if p_l < 0.01 else ' (*)' if p_l < 0.05 else ' (n.s.)' ax3.text(0.98, 0.04, sig_text3, transform=ax3.transAxes, ha='right', fontsize=9.5, color='#333', bbox=dict(boxstyle='round,pad=0.3', facecolor='#FFF9C4', edgecolor='#F9A825', alpha=0.8)) plt.tight_layout() fig3.savefig(os.path.join(FIG_DIR, '2023_H5_5_fig3_land.png'), bbox_inches='tight', dpi=150) plt.close(fig3) print("図3保存: 2023_H5_5_fig3_land.png") |
図3保存: 2023_H5_5_fig3_land.png
s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。2022年度の47都道府県を食料費割合でランキングし、食料依存度の地域格差を可視化する。
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | import numpy as np import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import statsmodels.api as sm from scipy import stats 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' DATA_DIR = 'data/raw' 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} のように書式も指定できます。171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | print("\n■ 時系列分析:消費支出内訳の推移(全国平均)") ts = df_pref.groupby(year_col)[['L3221', 'L322101', 'L322108', 'L322109']].mean() ts['food_pct'] = ts['L322101'] / ts['L3221'] * 100 # 食料費割合(%) ts['edu_pct'] = ts['L322108'] / ts['L3221'] * 100 # 教育費割合(%) ts['ent_pct'] = ts['L322109'] / ts['L3221'] * 100 # 教養娯楽費割合(%) ts = ts.sort_index() print("\n 年度 食料費% 教育費% 教養娯楽費%") print(" " + "-" * 38) for yr, row in ts.iterrows(): print(f" {int(yr)} {row['food_pct']:6.2f} {row['edu_pct']:5.2f} {row['ent_pct']:6.2f}") # 時系列トレンド検定(Mann-Kendall 代替: ピアソン相関 vs 年) years_arr = ts.index.values.astype(float) r_food, p_food = stats.pearsonr(years_arr, ts['food_pct'].values) r_edu, p_edu = stats.pearsonr(years_arr, ts['edu_pct'].values) r_ent, p_ent = stats.pearsonr(years_arr, ts['ent_pct'].values) print(f"\n 食料費割合 トレンド: r={r_food:.4f}, p={p_food:.4f}") print(f" 教育費割合 トレンド: r={r_edu:.4f}, p={p_edu:.4f}") print(f" 教養娯楽費 トレンド: r={r_ent:.4f}, p={p_ent:.4f}") |
■ 時系列分析:消費支出内訳の推移(全国平均) 年度 食料費% 教育費% 教養娯楽費% -------------------------------------- 2012 23.27 3.95 9.66 2013 23.36 3.79 9.73 2014 23.81 3.92 9.65 2015 24.85 3.64 9.70 2016 25.16 3.84 9.57 2017 25.39 3.75 9.60 2018 25.49 3.87 9.41 2019 25.54 3.78 9.63 2020 27.02 3.62 8.71 2021 26.67 3.80 8.56 2022 26.45 3.68 8.97 2023 27.24 3.24 9.26 食料費割合 トレンド: r=0.9607, p=0.0000 教育費割合 トレンド: r=-0.6599, p=0.0195 教養娯楽費 トレンド: r=-0.7365, p=0.0063
df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。192 193 194 195 196 197 | print("\n" + "=" * 60) print("■ 横断面分析(2022年度)") print("=" * 60) df_2022 = df_pref[df_pref[year_col] == 2022].copy().reset_index(drop=True) print(f" 対象: {len(df_2022)}都道府県(2022年度)") |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。198 199 200 201 202 203 204 205 206 207 208 | # 目的変数:食料費割合(代理変数) df_2022['food_ratio'] = df_2022['L322101'] / df_2022['L3221'] * 100 # 説明変数 df_2022['aging_rate'] = df_2022['A1303'] / df_2022['A1101'] * 100 # 高齢化率(%) df_2022['outflow_rate'] = df_2022['A5102'] / df_2022['A1101'] * 100 # 転出率(%) VAR_NAMES = ['高齢化率', '消費支出', '住宅地価格', '気温', '降水量', '転出率'] VAR_COLS = ['aging_rate', 'L3221', 'C5401', 'B4101', 'B4109', 'outflow_rate'] y_vals = df_2022['food_ratio'].values X_raw = df_2022[VAR_COLS].values |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。209 210 211 212 213 214 215 | # 欠損除外 valid = np.all(np.isfinite(X_raw), axis=1) & np.isfinite(y_vals) X_raw = X_raw[valid] y_vals = y_vals[valid] pref_names = df_2022.loc[valid, 'Prefecture'].values N = len(y_vals) print(f" 有効都道府県数: N={N}") |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。216 217 218 219 220 221 222 223 224 225 226 227 | # 無相関検定 print("\n 無相関検定(ピアソン相関)") print(f" {'変数':<12} {'r':>8} {'p値':>10} {'有意':>6}") print(" " + "-" * 40) corrs_all = [] pvals_all = [] for name, col in zip(VAR_NAMES, X_raw.T): r, p = stats.pearsonr(col, y_vals) sig = '***' if p < 0.001 else '**' if p < 0.01 else '*' if p < 0.05 else 'n.s.' print(f" {name:<12} {r:>8.4f} {p:>10.4f} {sig:>6}") corrs_all.append(r) pvals_all.append(p) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。228 229 230 231 232 233 234 | # 重回帰分析 print("\n■ 重回帰分析(全変数投入 OLS)") X_sm = sm.add_constant(X_raw) model_full = sm.OLS(y_vals, X_sm).fit() print(f" R² = {model_full.rsquared:.4f}, 調整R² = {model_full.rsquared_adj:.4f}") print(f" F統計量 p = {model_full.f_pvalue:.4f}") print(model_full.summary2()) |
============================================================
■ 横断面分析(2022年度)
============================================================
対象: 47都道府県(2022年度)
有効都道府県数: N=47
無相関検定(ピアソン相関)
変数 r p値 有意
----------------------------------------
高齢化率 -0.2410 0.1027 n.s.
消費支出 -0.2811 0.0556 n.s.
住宅地価格 0.3452 0.0175 *
気温 -0.1445 0.3326 n.s.
降水量 0.0997 0.5050 n.s.
転出率 0.2071 0.1626 n.s.
■ 重回帰分析(全変数投入 OLS)
R² = 0.4740, 調整R² = 0.3951
F統計量 p = 0.0002
Results: Ordinary least squares
=================================================================
Model: OLS Adj. R-squared: 0.395
Dependent Variable: y AIC: 147.2610
Date: 2026-05-18 11:24 BIC: 160.2121
No. Observations: 47 Log-Likelihood: -66.631
Df Model: 6 F-statistic: 6.008
Df Residuals: 40 Prob (F-statistic): 0.000152
R-squared: 0.474 Scale: 1.1720
-------------------------------------------------------------------
Coef. Std.Err. t P>|t| [0.025 0.975]
-------------------------------------------------------------------
const 45.6322 4.8438 9.4207 0.0000 35.8424 55.4219
x1 -0.1406 0.0749 -1.8783 0.0676 -0.2919 0.0107
x2 -0.0000 0.0000 -4.4377 0.0001 -0.0001 -0.0000
x3 0.0000 0.0000 1.9063 0.0638 -0.0000 0.0000
x4 -0.3011 0.0871 -3.4574 0.0013 -0.4771 -0.1251
x5 0.0005 0.0003 1.6827 0.1002 -0.0001 0.0012
x6 0.5134 0.8397 0.6114 0.5444 -1.1838 2.2106
-----------------------------------------------------------------
Omnibus: 0.329 Durbin-Watson: 1.888
Prob(Omnibus): 0.849 Jarque-Bera (JB): 0.505
Skew: -0.049 Prob(JB): 0.777
Kurtosis: 2.502 Condition No.: 9074527
=================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the
errors is correctly specified.
[2] The condition number is large, 9.07e+06. 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() で結果取得。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | fig4, ax4 = plt.subplots(figsize=(10, 8)) # 全47都道府県をソート、上位10件を強調 df_rank = pd.DataFrame({'Prefecture': pref_names, 'food_ratio': y_vals}) df_rank = df_rank.sort_values('food_ratio', ascending=True) # 横棒グラフ用に昇順 # 全都道府県を薄く描き、上位10を強調 bar_colors = [] threshold_top10 = df_rank['food_ratio'].nlargest(10).min() for val in df_rank['food_ratio']: if val >= threshold_top10: bar_colors.append('#C62828') # 上位10: 赤 else: bar_colors.append('#90CAF9') # それ以外: 薄い青 bars = ax4.barh(df_rank['Prefecture'], df_rank['food_ratio'], color=bar_colors, alpha=0.8, edgecolor='white', height=0.7) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | # 値ラベル(上位10のみ) for bar, val, pname in zip(bars, df_rank['food_ratio'], df_rank['Prefecture']): if val >= threshold_top10: ax4.text(val + 0.05, bar.get_y() + bar.get_height() / 2, f'{val:.1f}%', va='center', fontsize=8.5, fontweight='bold', color='#C62828') # 全国平均線 national_mean = np.mean(y_vals) ax4.axvline(national_mean, color='#FF8F00', linestyle='--', linewidth=1.8, label=f'全国平均 {national_mean:.1f}%', alpha=0.9) ax4.set_xlabel('食料費割合(食料費 / 消費支出 × 100, %)', fontsize=11) ax4.set_title('都道府県別 食料費割合(2022年)\n' '食料費割合が高い地域(赤)= 食料依存度が高い傾向', fontsize=12, fontweight='bold') ax4.legend(fontsize=10) ax4.grid(axis='x', alpha=0.3) ax4.set_xlim(left=df_rank['food_ratio'].min() - 1) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | # 凡例補足 from matplotlib.patches import Patch legend_elements = [ Patch(facecolor='#C62828', alpha=0.8, label=f'上位10都道府県(≥{threshold_top10:.1f}%)'), Patch(facecolor='#90CAF9', alpha=0.8, label='その他'), ] ax4.legend(handles=legend_elements + [plt.Line2D([0], [0], color='#FF8F00', linestyle='--', linewidth=1.8, label=f'全国平均 {national_mean:.1f}%')], fontsize=9, loc='lower right') plt.tight_layout() fig4.savefig(os.path.join(FIG_DIR, '2023_H5_5_fig4_rank.png'), bbox_inches='tight', dpi=150) plt.close(fig4) print("図4保存: 2023_H5_5_fig4_rank.png") print("\n" + "=" * 60) print("全図の生成完了(4枚)") print(f" fig1_ts.png : 消費支出内訳 時系列推移(2012〜2023)") print(f" fig2_temp.png : 気温 vs 食料費割合 散布図") print(f" fig3_land.png : 住宅地価格 vs 食料費割合 散布図") print(f" fig4_rank.png : 都道府県別 食料費割合 ランキング") print(f" 保存先: {os.path.abspath(FIG_DIR)}") print("=" * 60) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。293 294 295 296 297 298 299 | # 代理変数の注意書き print("\n【注意】本分析について") print(" 食料自給率(カロリーベース)は農林水産省が公表しており、") print(" SSDSE-Bには含まれていない。") print(" 本分析では「食料費 / 消費支出」を代理変数(proxy)として使用。") print(" この指標は家計の食料依存度を示すが、") print(" 食料自給率(国内生産量 / 消費量)とは概念が異なる点に注意。") |
図4保存: 2023_H5_5_fig4_rank.png ============================================================ 全図の生成完了(4枚) fig1_ts.png : 消費支出内訳 時系列推移(2012〜2023) fig2_temp.png : 気温 vs 食料費割合 散布図 fig3_land.png : 住宅地価格 vs 食料費割合 散布図 fig4_rank.png : 都道府県別 食料費割合 ランキング 保存先: /Users/shimpei/Dropbox/Works_Researches/2026 統計・データ解析コンペ/html/figures ============================================================ 【注意】本分析について 食料自給率(カロリーベース)は農林水産省が公表しており、 SSDSE-Bには含まれていない。 本分析では「食料費 / 消費支出」を代理変数(proxy)として使用。 この指標は家計の食料依存度を示すが、 食料自給率(国内生産量 / 消費量)とは概念が異なる点に注意。
plt.subplots(figsize=(W, H)) で図サイズ指定、fig.savefig(..., bbox_inches='tight') で余白を自動で詰めて保存。本分析は「食料費割合」を代理変数として使用しており、農林水産省公表の「食料自給率(カロリーベース)」とは異なる指標である点を強調する。代理変数を使う場合は常に「真の指標との乖離」を認識し、結論を慎重に述べることが科学的誠実さにつながる。
| データ | 出典 |
|---|---|
| SSDSE-B 都道府県データ(2026年版) | 統計数理研究所 SSDSE(https://www.nstac.go.jp/use/literacy/ssdse/) |
| 食料自給率(参考値) | 農林水産省 食料需給表(https://www.maff.go.jp/j/zyukyu/) |
| 家計調査(消費支出内訳) | 総務省 家計調査(SSDSE-B L列に収録) |
本教育用コードはSSDSE-B-2026.csvの実データを使用(合成データは使用していません)。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。