この教材は、原論文が使ったデータそのものを使えていません。そこで代わりのデータで同じ問いを追いかけ、結論の向き(増える/減る、強い/弱い)が原論文と一致するかを確かめます。「同じ数値が出る」ことは目標にしていません。
| 原論文が使ったデータ | SSDSE-C・SSDSE-D・家計調査 分析単位:都道府県 |
|---|---|
| この教材が使うデータ |
|
| 原論文(PDF) | 行動制限下における家計消費の変化に伴う経済波及効果の算出 統計活用奨励賞/井手 健太(法政大学大学院経済学研究科/東京都総務局統計部調整課)山口 真菜(東京都総務局統計部調整課) |
原論文と同じ粒度のデータは、この教材にも同梱しています。これを読み込めば、原論文と同じ細かさで分析をやり直せます(下の「🐍 ブラウザで動かす」でコードを書き換えて試せます)。ただし原論文が使った項目がすべて収録されているとは限りません。足りない項目は、上の「できないこと」に書いた出典から取ってくる必要があります。
▶ ここに書いてある分析は、ページ下部の「🐍 ブラウザで動かす」でそのまま実行できます(インストール不要)。動かしているのは code/2023_U4_katsuyo.py(333 行)そのものです。
このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
新型コロナウイルス感染症(COVID-19)の拡大に伴い、政府・自治体は2020〜2021年にかけて外出自粛・緊急事態宣言・まん延防止等重点措置などの行動制限を実施した。これらの措置は家計の消費行動を大きく変容させ、特に外食・観光・娯楽といった「接触集約型」の消費を直撃した一方、食料費は微増という代替効果も生じた。
原論文の概要(統計センター公式):「新型コロナウィルス感染症に伴う行動制限下で人々の消費にどのような変化があったか、またどのような経済波及効果があったか家計調査のデータを用いて分析を行い、家計消費支出や生産誘発額が大きく減少したことを示した。」
本ページではこの分析の流れを実データでたどりながら、使われた統計手法を一つずつ学んでいく。
本研究は、SSDSE-B(都道府県別パネルデータ)を用いて、(1)消費カテゴリごとの時系列変化、(2)行動制限前・中・後の3期間比較、(3)都道府県間のOLS回帰による消費支出変化のメカニズム分析、(4)簡易乗数モデルによる経済波及効果の粗推計を行う。
SSDSE-B 時系列分析 変化率比較 OLS回帰 経済波及効果
SSDSE(社会・人口統計体系データセット)-B は都道府県レベルの統計を収録したパネルデータである。本分析では2012〜2023年の12年分、47都道府県のデータを用いる。
| 項目 | 内容 |
|---|---|
| 出典 | 統計センター SSDSE-B(2026年版) |
| 観測単位 | 都道府県(47)× 年度(12年)= 564 観測 |
| 分析期間 | 2012〜2023年度 |
| 行動制限期間 | 2020・2021年度(COVID-19拡大期) |
| 比較基準年 | 2019年度(コロナ前最終年) |
| 変数名(SSDSE-B) | カテゴリ | COVID影響の方向性 |
|---|---|---|
| 消費支出(二人以上の世帯) | 総消費支出 | 全体的に減少 |
| 食料費(二人以上の世帯) | 食料費 | 外食減・内食増(微増) |
| 教養娯楽費(二人以上の世帯) | 教養娯楽費 | 最大の打撃(旅行・外出禁止) |
| 交通・通信費(二人以上の世帯) | 交通・通信費 | 移動制限により減少 |
| 住居費(二人以上の世帯) | 住居費 | 在宅増加で微増/横ばい |
| 保健医療費(二人以上の世帯) | 保健医療費 | 受診控えで減少 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | df_b = pd.read_csv(DATA_B, encoding='cp932', header=1) # 都道府県レベル(R01000〜R47000)のみ抽出 df_b = df_b[df_b['地域コード'].str.match(r'^R\d{5}$', na=False)].copy() # 消費支出カラム名(SSDSE-B 実際のカラム名) COL_TOTAL = '消費支出(二人以上の世帯)' COL_FOOD = '食料費(二人以上の世帯)' COL_ENT = '教養娯楽費(二人以上の世帯)' COL_TRANS = '交通・通信費(二人以上の世帯)' COL_HOUSE = '住居費(二人以上の世帯)' COL_HEALTH = '保健医療費(二人以上の世帯)' COLS_ALL = [COL_TOTAL, COL_FOOD, COL_ENT, COL_TRANS, COL_HOUSE, COL_HEALTH] COLS_5 = [COL_FOOD, COL_ENT, COL_TRANS, COL_HOUSE, COL_HEALTH] # 5カテゴリ for col in COLS_ALL: df_b[col] = pd.to_numeric(df_b[col], errors='coerce') df_b['年度'] = pd.to_numeric(df_b['年度'], 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ループ不要なのが強み。20 21 22 23 24 25 26 27 | # 全国平均(都道府県平均)を年度別に集計 nat_avg = df_b.groupby('年度')[COLS_ALL].mean() years = nat_avg.index.to_numpy() # 2012-2023 print("データ読み込み完了") print(f" 年度: {years}") print(f" 都道府県数: {df_b['地域コード'].nunique()}") print(nat_avg[[COL_TOTAL, COL_ENT]].to_string()) |
データ読み込み完了
年度: [2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023]
都道府県数: 47
消費支出(二人以上の世帯) 教養娯楽費(二人以上の世帯)
年度
2012 286665.319149 27686.723404
2013 288887.617021 28109.723404
2014 290113.787234 27996.914894
2015 286153.085106 27753.957447
2016 287056.170213 27483.446809
2017 286288.340426 27474.787234
2018 288162.808511 27105.085106
2019 288524.914894 27774.255319
2020 279687.638298 24353.340426
2021 281003.404255 24051.170213
2022 289630.361702 25973.765957
2023 295856.021277 27409.148936df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。5つの消費カテゴリの月額支出を2012〜2023年の時系列で可視化する。行動制限期間(2020〜2021年)をオレンジシェードで強調し、2019年(基準年)を破線で示す。
複数カテゴリを同一グラフに描く際、COVID効果を「シェード」で強調するのは視覚的に効果的。構造変化点(2020年)の前後でトレンドが変わっているかをDiff-in-Diff(差の差)的思考で確認することが重要。
29 30 31 32 33 34 | fig, ax = plt.subplots(figsize=(11, 6)) for col in COLS_5: vals = nat_avg[col].values / 1000 # 円 → 千円 ax.plot(years, vals, marker='o', markersize=5, color=CAT_COLORS[col], label=CAT_LABELS[col], lw=2) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | # 行動制限期間シェード ax.axvspan(COVID_START - 0.5, COVID_END + 0.5, color='#FFCC80', alpha=0.35, zorder=0, label='行動制限期間 (2020-2021)') # 基準線(2019) ax.axvline(2019, color='gray', lw=1.2, linestyle='--', alpha=0.7, label='2019年(基準)') ax.set_xlabel('年度', fontsize=12) ax.set_ylabel('月額支出(千円)', fontsize=12) ax.set_title('図1: 家計消費支出の推移(2012〜2023年、都道府県平均)', fontsize=13) ax.set_xticks(years) ax.set_xticklabels([str(y) for y in years], rotation=45, ha='right') ax.legend(fontsize=10, loc='upper left') ax.grid(True, axis='y', alpha=0.3) ax.grid(True, axis='x', alpha=0.15) plt.tight_layout() fig1_path = os.path.join(FIG_DIR, '2023_U4_fig1_timeseries.png') plt.savefig(fig1_path, dpi=150) plt.close() print(f"fig1 saved: {fig1_path}") |
fig1 saved: html/figures/2023_U4_fig1_timeseries.png
ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。2019年を基準(0%)として、「コロナ前(2018-2019年平均)」「行動制限下(2020-2021年平均)」「緩和後(2022-2023年平均)」の3期間における各カテゴリの変化率を算出し集合棒グラフで比較する。
| カテゴリ | コロナ前 (2018-19) | 行動制限下 (2020-21) | 緩和後 (2022-23) |
|---|---|---|---|
| 食料費 | −0.1% | +2.3% | +6.8% |
| 教養娯楽費 | −0.8% | −12.2% | −3.4% |
| 消費支出(総計) | +0.1% | −2.6% | +1.9% |
「行動制限の影響」を測る際、2020年単年だけでなく2020・2021年の「2年平均」を使うことで、年による揺れを平準化できる。比較基準(2019年)は固定し、各期間は平均値と比較するのが標準的な手法。
57 58 59 60 61 62 63 64 | periods = { 'コロナ前\n(2018-2019)': df_b[df_b['年度'].isin([2018, 2019])].groupby('都道府県')[COLS_5].mean(), '行動制限下\n(2020-2021)': df_b[df_b['年度'].isin([2020, 2021])].groupby('都道府県')[COLS_5].mean(), '緩和後\n(2022-2023)': df_b[df_b['年度'].isin([2022, 2023])].groupby('都道府県')[COLS_5].mean(), } # 2019年 都道府県別基準 base_pref = df_b[df_b['年度'] == 2019].groupby('都道府県')[COLS_5].mean() |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。65 66 67 68 69 70 71 72 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 | # 各期間の全国平均変化率(%) period_names = list(periods.keys()) change_pct = {} for pname, pdata in periods.items(): common_pref = pdata.index.intersection(base_pref.index) diff_pct = ((pdata.loc[common_pref] - base_pref.loc[common_pref]) / base_pref.loc[common_pref] * 100) change_pct[pname] = diff_pct.mean() # 全国平均 n_periods = len(period_names) n_cats = len(COLS_5) x_base = np.arange(n_periods) width = 0.15 offsets = np.linspace(-(n_cats - 1) / 2, (n_cats - 1) / 2, n_cats) * width fig, ax = plt.subplots(figsize=(11, 6)) for i, col in enumerate(COLS_5): vals = [change_pct[p][col] for p in period_names] bars = ax.bar(x_base + offsets[i], vals, width=width * 0.92, color=CAT_COLORS[col], label=CAT_LABELS[col], alpha=0.85) for bar, v in zip(bars, vals): ypos = bar.get_height() if v >= 0 else bar.get_height() - 0.3 ax.text(bar.get_x() + bar.get_width() / 2, ypos + (0.15 if v >= 0 else -0.8), f'{v:+.1f}%', ha='center', va='bottom', fontsize=7.5, rotation=90) ax.axhline(0, color='black', lw=1.0) ax.set_xticks(x_base) ax.set_xticklabels(period_names, fontsize=11) ax.set_ylabel('2019年比 変化率(%)', fontsize=12) ax.set_title('図2: 消費カテゴリ別 2019年基準変化率(都道府県平均)', fontsize=13) ax.legend(fontsize=10, loc='lower right') ax.grid(True, axis='y', alpha=0.3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。99 100 101 102 103 104 105 106 107 | # 行動制限期帯を背景色で区別 ax.axvspan(0.5, 1.5, color='#FFCC80', alpha=0.25, zorder=0) ax.text(1, ax.get_ylim()[0] + 0.1, '行動制限下', ha='center', fontsize=9, color='#E65100') plt.tight_layout() fig2_path = os.path.join(FIG_DIR, '2023_U4_fig2_pct_change.png') plt.savefig(fig2_path, dpi=150) plt.close() print(f"fig2 saved: {fig2_path}") |
fig2 saved: html/figures/2023_U4_fig2_pct_change.png
fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。都道府県を観察単位として、2019→2020年の「教養娯楽費変化率」(横軸)と「食料費変化率」(縦軸)の関係を散布図で可視化し、OLS回帰直線を重ねる。娯楽支出が大きく落ちた都道府県で食料費がどう動いたかを探る。
回帰分析では「係数(β)」「決定係数(R²)」「p値」を必ずセットで報告する。係数は1単位変化の効果、R²はモデルの説明力、p値は偶然による可能性。p<0.001は「非常に強い統計的根拠あり」を意味するが、R²=0.51は残り49%が他の要因であることも示す。
109 110 111 112 113 114 115 116 117 | df_2019 = df_b[df_b['年度'] == 2019].set_index('都道府県') df_2020 = df_b[df_b['年度'] == 2020].set_index('都道府県') common_prefs = df_2019.index.intersection(df_2020.index) ent_chg = ((df_2020.loc[common_prefs, COL_ENT] - df_2019.loc[common_prefs, COL_ENT]) / df_2019.loc[common_prefs, COL_ENT] * 100) food_chg = ((df_2020.loc[common_prefs, COL_FOOD] - df_2019.loc[common_prefs, COL_FOOD]) / df_2019.loc[common_prefs, COL_FOOD] * 100) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。118 119 120 121 122 123 124 125 126 127 | # OLS回帰直線 slope, intercept, r_val, p_val, se_slope = stats.linregress(ent_chg.values, food_chg.values) x_line = np.linspace(ent_chg.min() - 1, ent_chg.max() + 1, 200) y_line = slope * x_line + intercept fig, ax = plt.subplots(figsize=(9, 7)) ax.scatter(ent_chg.values, food_chg.values, color='#1565C0', alpha=0.75, s=55, zorder=3) ax.plot(x_line, y_line, color='#C62828', lw=2, linestyle='--', label=f'回帰直線 (r={r_val:.3f}, p={p_val:.4f})') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | # 都道府県名ラベル(上位・下位5件のみ) ent_sorted = ent_chg.sort_values() label_prefs = list(ent_sorted.index[:3]) + list(ent_sorted.index[-3:]) for pref in label_prefs: ax.annotate(pref, (ent_chg[pref], food_chg[pref]), fontsize=8, xytext=(4, 4), textcoords='offset points', color='#333333') ax.axhline(0, color='gray', lw=0.8, linestyle=':') ax.axvline(0, color='gray', lw=0.8, linestyle=':') ax.set_xlabel('教養娯楽費 変化率(2020 vs 2019、%)', fontsize=12) ax.set_ylabel('食料費 変化率(2020 vs 2019、%)', fontsize=12) ax.set_title('図3: 教養娯楽費変化 vs 食料費変化(都道府県別、2020年)', fontsize=13) ax.legend(fontsize=11) ax.grid(True, alpha=0.3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | # 象限ラベル ax.text(ax.get_xlim()[1] * 0.98, ax.get_ylim()[1] * 0.95, '娯楽↑食料↑', ha='right', va='top', fontsize=9, color='#555') ax.text(ax.get_xlim()[0] * 0.98, ax.get_ylim()[1] * 0.95, '娯楽↓食料↑', ha='left', va='top', fontsize=9, color='#555') ax.text(ax.get_xlim()[1] * 0.98, ax.get_ylim()[0] * 0.95, '娯楽↑食料↓', ha='right', va='bottom', fontsize=9, color='#555') ax.text(ax.get_xlim()[0] * 0.98, ax.get_ylim()[0] * 0.95, '娯楽↓食料↓', ha='left', va='bottom', fontsize=9, color='#555') plt.tight_layout() fig3_path = os.path.join(FIG_DIR, '2023_U4_fig3_scatter.png') plt.savefig(fig3_path, dpi=150) plt.close() print(f"fig3 saved: {fig3_path}") |
fig3 saved: html/figures/2023_U4_fig3_scatter.png
fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。2020年の消費支出変化率(2019年比)が最も大きかった(=最も減少した)都道府県をランキングで示す。行動制限の影響は全国一律ではなく、観光業・サービス業への依存度によって地域差が生じると考えられる。
| 順位 | 都道府県 | 消費支出変化率 | 考えられる要因 |
|---|---|---|---|
| 1 | 石川県 | −15.7% | 観光・伝統工芸産業への依存、金沢の観光需要急減 |
| 2 | 岡山県 | −14.4% | 外出自粛による娯楽・外食消費の急減 |
| 3 | 長野県 | −14.2% | 観光・スキーリゾート需要の消滅 |
| 4 | 福井県 | −11.5% | 小規模経済での行動制限の大きな影響 |
| 5 | 香川県 | −10.7% | 観光(瀬戸内・うどん文化)需要の低迷 |
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | total_chg_abs = (df_2020.loc[common_prefs, COL_TOTAL] - df_2019.loc[common_prefs, COL_TOTAL]) # 円(月額、マイナスが削減) total_chg_pct = total_chg_abs / df_2019.loc[common_prefs, COL_TOTAL] * 100 # 削減が大きい順(変化率の小さい=最も下がった)トップ10 top10 = total_chg_pct.sort_values().head(10) fig, ax = plt.subplots(figsize=(10, 6)) colors_bar = ['#C62828' if v < -5 else ('#EF6C00' if v < -2 else '#1565C0') for v in top10.values] bars = ax.barh(top10.index[::-1], top10.values[::-1], color=colors_bar[::-1], alpha=0.85) for bar, v in zip(bars, top10.values[::-1]): ax.text(v - 0.05, bar.get_y() + bar.get_height() / 2, f'{v:+.1f}%', va='center', ha='right', fontsize=10, fontweight='600', color='white') ax.axvline(total_chg_pct.mean(), color='navy', lw=1.5, linestyle='--', label=f'全国平均 {total_chg_pct.mean():+.1f}%') ax.set_xlabel('消費支出変化率(2020 vs 2019、%)', fontsize=12) ax.set_title('図4: 消費支出削減が大きかった都道府県 トップ10(2020年 vs 2019年)', fontsize=13) ax.legend(fontsize=11) ax.grid(True, axis='x', alpha=0.3) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。183 184 185 186 187 188 189 190 191 192 193 194 195 196 | # 凡例パッチ p1 = mpatches.Patch(color='#C62828', alpha=0.85, label='−5%超の削減') p2 = mpatches.Patch(color='#EF6C00', alpha=0.85, label='−2〜−5%の削減') p3 = mpatches.Patch(color='#1565C0', alpha=0.85, label='−2%未満の削減') ax.legend(handles=[p1, p2, p3, plt.Line2D([0], [0], color='navy', lw=1.5, linestyle='--', label=f'全国平均 {total_chg_pct.mean():+.1f}%')], fontsize=10, loc='lower right') plt.tight_layout() fig4_path = os.path.join(FIG_DIR, '2023_U4_fig4_top10.png') plt.savefig(fig4_path, dpi=150) plt.close() print(f"fig4 saved: {fig4_path}") |
fig4 saved: html/figures/2023_U4_fig4_top10.png
fig.savefig(..., bbox_inches='tight') — 余白を自動で詰めて保存。plt.close() でメモリ解放。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。産業連関分析(Input-Output Analysis)の考え方を応用し、消費支出の変化が経済全体に及ぼす波及効果を粗く推計する。ここでは家計消費乗数の単純な考え方を用いる。
経済波及効果の正確な推計には総務省「産業連関表」が必要だが、基本的な思考は「1円の消費変化 → 乗数 × 1円のGDP変化」。統計データ分析の文脈では、消費変化の「大きさ・方向・カテゴリ別内訳」を丁寧に記述することが第一歩。
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | import os import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.patches as mpatches import numpy as np import pandas as pd from scipy import stats plt.rcParams['font.family'] = 'Hiragino Sans' plt.rcParams['axes.unicode_minus'] = False _dir = os.path.dirname(os.path.abspath(__file__)) FIG_DIR = os.path.join(_dir, '..', 'html', 'figures') DATA_B = os.path.join(_dir, '..', 'data', 'raw', 'SSDSE-B-2026.csv') 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} のように書式も指定できます。215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | CAT_LABELS = { COL_FOOD: '食料費', COL_ENT: '教養娯楽費', COL_TRANS: '交通・通信費', COL_HOUSE: '住居費', COL_HEALTH: '保健医療費', } CAT_COLORS = { COL_FOOD: '#1565C0', COL_ENT: '#C62828', COL_TRANS: '#2E7D32', COL_HOUSE: '#E65100', COL_HEALTH: '#6A1B9A', } COVID_START = 2020 COVID_END = 2021 # 2019年基準値(変化率計算用) base_nat = nat_avg.loc[2019] |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。235 236 237 238 239 240 241 242 243 244 245 246 | print("\n" + "="*60) print("簡易経済乗数の推計 (全国平均)") print("="*60) # 全47都道府県の2020年 消費支出変化率 vs 教養娯楽費変化率 ols_x = ent_chg.values ols_y = total_chg_pct.loc[common_prefs].values slope_main, intercept_main, r_main, p_main, se_main = stats.linregress(ols_x, ols_y) print(f"OLS: 消費支出変化率 = {intercept_main:.3f} + {slope_main:.3f} × 教養娯楽費変化率") print(f" R² = {r_main**2:.4f}, p = {p_main:.4f}, SE(slope) = {se_main:.4f}") |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。247 248 249 250 251 252 253 254 255 256 257 258 259 260 | # 粗い乗数推計: 全国平均消費支出削減額 nat_2019_total = nat_avg.loc[2019, COL_TOTAL] nat_2020_total = nat_avg.loc[2020, COL_TOTAL] delta_monthly = nat_2020_total - nat_2019_total # 月額円 delta_annual = delta_monthly * 12 * 47 # 47都道府県年額(簡易) print(f"\n全国平均消費支出: 2019年 {nat_2019_total:,.0f}円/月 → 2020年 {nat_2020_total:,.0f}円/月") print(f" 月額変化: {delta_monthly:+,.0f}円({delta_monthly/nat_2019_total*100:+.1f}%)") print(f" 簡易年間削減額(47都道府県合計参考値): {delta_annual/1e8:,.0f}億円") print(f"\n教養娯楽費: 2019年 {nat_avg.loc[2019, COL_ENT]:,.0f}円/月 → 2020年 {nat_avg.loc[2020, COL_ENT]:,.0f}円/月") ent_delta_pct = (nat_avg.loc[2020, COL_ENT] - nat_avg.loc[2019, COL_ENT]) / nat_avg.loc[2019, COL_ENT] * 100 print(f" 変化率: {ent_delta_pct:+.1f}%(最も大きな削減)") print("\n全4図の生成が完了しました。") |
============================================================ 簡易経済乗数の推計 (全国平均) ============================================================ OLS: 消費支出変化率 = 2.802 + 0.480 × 教養娯楽費変化率 R² = 0.5110, p = 0.0000, SE(slope) = 0.0699 全国平均消費支出: 2019年 288,525円/月 → 2020年 279,688円/月 月額変化: -8,837円(-3.1%) 簡易年間削減額(47都道府県合計参考値): -0億円 教養娯楽費: 2019年 27,774円/月 → 2020年 24,353円/月 変化率: -12.3%(最も大きな削減) 全4図の生成が完了しました。
np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。原論文は SSDSE-C/D の家計消費データから行動制限下の消費変化を捉え、経済波及効果を算出しました。同じ SSDSE-C-2026 で、外食・中食・内食の構成を確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 | c = pd.read_csv('data/raw/SSDSE-C-2026.csv', encoding='cp932', header=1) c = c[c['地域コード'] != 'R00000'].set_index('都道府県') cv = lambda x: pd.to_numeric(c[x], errors='coerce') items = {'外食': '12 外食', '調理食品': '09 調理食品', '穀類': '01 穀類'} total = cv('食料(合計)') print('食料支出に占める割合(%):') for label, col in items.items(): share = cv(col) / total * 100 print(f' {label:6s} 全国平均 {share.mean():.1f}% 最高: {share.idxmax()} {share.max():.1f}% / 最低: {share.idxmin()} {share.min():.1f}%') r, p = stats.pearsonr(cv('12 外食') / total, cv('09 調理食品') / total) print(f'外食割合 × 調理食品割合: r = {r:+.3f} (p={p:.4f})') print('→ 外食と中食(調理食品)の代替関係。行動制限はこの構成を外食→内食側へ動かした(原論文の分析対象)') |
| データ | 出典 |
|---|---|
| SSDSE-B(都道府県別パネルデータ 2012〜2023年) | 統計センター SSDSE(社会・人口統計体系) |
| 家計調査(二人以上の世帯 消費支出) | 総務省統計局(SSDSE-B に収録) |
本コードは実データ(SSDSE-B-2026.csv)のみを使用。合成データ・np.random による生成は一切含まない。教育目的の再現コード。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。
この論文を理解できたか、クリックで確認しましょう。間違えても解説が出ます。
このページの分析は、この画面の中でそのまま実行できます。
Python をインストールする必要も、CSV をダウンロードする必要もありません。
下のセルの 「▶ ブラウザで実行」 を上から順に押すか、
「▶ 最初から全部実行」 で一気に流してください。
表示されるのは、本文の図表とまったく同じ計算の結果です
(動かしているのは再現スクリプト code/2023_U4_katsuyo.py そのもの)。
コードは書き換えられます。「✏️ 書き換える」で数字や変数を変えて ▶ を押すと、 結果がどう変わるかをその場で確かめられます(元に戻すボタンつき)。 ページを開いた時点で裏で実行環境の準備が始まっているので、待ち時間はほとんどありません。 初回だけ実行環境の取得にインターネット接続が必要です。