このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
日本は南北に細長い地形を持ち、北海道・東北地方と沖縄・九州南部では年平均気温が10℃以上異なる。この気候の差異は、暖房・冷房需要を通じて家計の光熱費負担に大きく影響する。本研究は「地域の気温が光熱水道費の家計負担にどの程度影響するか」を、47都道府県の公的統計データを用いて定量的に分析した。
まず「気温と光熱・水道費地域気候が家計エネルギー支出に与える影響」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
SSDSE-B 都道府県データ Pearson 相関分析 OLS 重回帰 時系列分析 散布図
SSDSE(社会・人口統計体系データセット)-B は47都道府県の多分野統計を収録する。本分析では2022年断面データ(n=47)を主に使用し、時系列分析では2012〜2023年を使用する。
| 変数名 | 定義 | SSDSE-B 列名 | 想定方向 |
|---|---|---|---|
| 光熱水道費割合 | 光熱・水道費 / 消費支出 × 100(%) | 光熱・水道費(二人以上の世帯) ÷ 消費支出(二人以上の世帯) |
目的変数 |
| 光熱水道費_万円 | 光熱・水道費(円)÷ 10,000 | 光熱・水道費(二人以上の世帯) | 参考 |
| 年平均気温 | 年間の日平均気温の平均(℃) | 年平均気温 | 負(−) |
| 最高気温 | 日最高気温の月平均の最高値(℃) | 最高気温(日最高気温の月平均の最高値) | — |
| 最低気温 | 日最低気温の月平均の最低値(℃) | 最低気温(日最低気温の月平均の最低値) | 正(+)? |
| 高齢化率 | 65歳以上人口 ÷ 総人口 × 100(%) | 65歳以上人口 ÷ 総人口 | 正(+) |
| 消費支出_log | 消費支出(円)の自然対数 | 消費支出(二人以上の世帯) | 負(−) |
まず47都道府県の年平均気温を低い順に並べ、寒冷地(青)・温暖地(橙)・その他(灰)を色分けして可視化する。北海道・東北が低温側に、沖縄・九州南部が高温側に集中していることを確認する。
「年平均気温が高いほど光熱費割合が低い」という負の相関は、単純な因果関係ではない。背景にあるメカニズムを理解することが重要:
(1)寒冷地は冬季の暖房需要が大きく(灯油・ガス消費増)、(2)温暖地は夏季の冷房需要があるが、暖房と比べると電気代への影響は小さい。(3)そのため年間トータルでは寒冷地の方が光熱費負担が大きくなる。
1 2 3 4 5 6 7 8 9 10 11 12 13 | import os import warnings import numpy as np import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.patches as mpatches from matplotlib import rcParams import statsmodels.api as sm from scipy import stats warnings.filterwarnings('ignore') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。matplotlib.use('Agg') — グラフを画面表示せずファイルに保存するためのおまじない。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。14 15 16 17 18 19 20 21 22 23 | # ── パス設定 ────────────────────────────────────────────────────────────────── FIG_DIR = 'html/figures' DATA_B = 'data/raw/SSDSE-B-2026.csv' os.makedirs(FIG_DIR, exist_ok=True) # ── フォント設定 ─────────────────────────────────────────────────────────────── rcParams['font.family'] = ['Hiragino Sans', 'Hiragino Kaku Gothic ProN', 'AppleGothic', 'Noto Sans CJK JP', 'sans-serif'] rcParams['axes.unicode_minus'] = False |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。os.makedirs('html/figures', exist_ok=True) — 図の保存先フォルダを作る(既にあってもOK)。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # ── データ読み込み ───────────────────────────────────────────────────────────── df_raw = pd.read_csv(DATA_B, header=[0, 1], encoding='cp932') # カラム名を平坦化(第2レベルを使用) df_raw.columns = [b if b not in ('', 'Unnamed: 0_level_1') else a for a, b in df_raw.columns] COL_YEAR = '年度' COL_PREF = '都道府県' COL_TEMP = '年平均気温' COL_TMAX = '最高気温(日最高気温の月平均の最高値)' COL_TMIN = '最低気温(日最低気温の月平均の最低値)' COL_ENER = '光熱・水道費(二人以上の世帯)' COL_CONS = '消費支出(二人以上の世帯)' COL_POP65 = '65歳以上人口' COL_POP = '総人口' |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。40 41 42 43 44 45 | # 必要列を選択 cols_needed = [COL_YEAR, COL_PREF, COL_TEMP, COL_TMAX, COL_TMIN, COL_ENER, COL_CONS, COL_POP65, COL_POP] df = df_raw[cols_needed].copy() df = df.dropna(subset=[COL_TEMP, COL_ENER, COL_CONS]) df[COL_YEAR] = df[COL_YEAR].astype(int) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.astype(int) — 列を整数に変換(年度などを数値比較するため)。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。46 47 48 49 50 51 52 | # 派生変数 df['光熱水道費_万円'] = df[COL_ENER] / 10000 df['光熱水道費割合'] = df[COL_ENER] / df[COL_CONS] * 100 df['高齢化率'] = df[COL_POP65] / df[COL_POP] * 100 df['消費支出_log'] = np.log(df[COL_CONS]) df['最高気温'] = df[COL_TMAX] df['最低気温'] = df[COL_TMIN] |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | # 2022年のみ抽出(メイン分析用) df22 = df[df[COL_YEAR] == 2022].copy().reset_index(drop=True) # 地域区分 KANREI = ['北海道', '青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県'] ONDAN = ['沖縄県', '鹿児島県', '宮崎県', '高知県', '愛媛県', '徳島県', '香川県', '福岡県', '佐賀県', '長崎県', '熊本県', '大分県'] def get_region(pref): if pref in KANREI: return '寒冷地' elif pref in ONDAN: return '温暖地' else: return 'その他' df22['地域区分'] = df22[COL_PREF].apply(get_region) df['地域区分'] = df[COL_PREF].apply(get_region) COLOR_MAP = {'寒冷地': '#1565C0', '温暖地': '#E65100', 'その他': '#78909C'} print(f"2022年データ: {len(df22)}都道府県") print(f"年平均気温 範囲: {df22[COL_TEMP].min():.1f}〜{df22[COL_TEMP].max():.1f}℃") print(f"光熱水道費割合 範囲: {df22['光熱水道費割合'].min():.1f}〜{df22['光熱水道費割合'].max():.1f}%") |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | # 相関係数(参考出力) r, p = stats.pearsonr(df22[COL_TEMP], df22['光熱水道費割合']) print(f"\n年平均気温 × 光熱水道費割合: r={r:.3f}, p={p:.4f}") df22_sorted = df22.sort_values(COL_TEMP, ascending=True).reset_index(drop=True) colors1 = [COLOR_MAP[g] for g in df22_sorted['地域区分']] fig1, ax1 = plt.subplots(figsize=(10, 11), dpi=150) bars = ax1.barh(range(len(df22_sorted)), df22_sorted[COL_TEMP], color=colors1, edgecolor='white', linewidth=0.5, height=0.8) ax1.set_yticks(range(len(df22_sorted))) ax1.set_yticklabels(df22_sorted[COL_PREF], fontsize=8.5) ax1.set_xlabel('年平均気温(℃)', fontsize=11) ax1.set_title('図1 都道府県別 年平均気温ランキング(2022年)\n寒冷地(青)は低温、温暖地(橙)は高温', fontsize=12, fontweight='bold', pad=12) ax1.axvline(df22[COL_TEMP].mean(), color='#333', linestyle='--', linewidth=1.2, alpha=0.7, label=f'全国平均 {df22[COL_TEMP].mean():.1f}℃') ax1.set_xlim(0, df22[COL_TEMP].max() + 2) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | # 気温の値ラベル for i, (val, pref) in enumerate(zip(df22_sorted[COL_TEMP], df22_sorted[COL_PREF])): ax1.text(val + 0.15, i, f'{val:.1f}', va='center', fontsize=7.5, color='#333') patch_k = mpatches.Patch(color='#1565C0', label='寒冷地(北海道・東北)') patch_o = mpatches.Patch(color='#E65100', label='温暖地(九州・四国南部)') patch_s = mpatches.Patch(color='#78909C', label='その他') ax1.legend(handles=[patch_k, patch_o, patch_s], loc='lower right', fontsize=9) ax1.grid(axis='x', alpha=0.3) ax1.spines['top'].set_visible(False) ax1.spines['right'].set_visible(False) fig1.tight_layout() fig1_path = os.path.join(FIG_DIR, '2022_H5_8_fig1_temp_ranking.png') fig1.savefig(fig1_path, dpi=150, bbox_inches='tight') plt.close(fig1) print(f"図1 保存: {fig1_path}") |
2022年データ: 47都道府県 年平均気温 範囲: 10.2〜23.7℃ 光熱水道費割合 範囲: 6.0〜13.0% 年平均気温 × 光熱水道費割合: r=-0.682, p=0.0000 findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Not …(長いため省略)
s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。年平均気温(℃)と光熱水道費割合(%)の散布図を描き、Pearson 相関係数と OLS 回帰直線を重ねる。都道府県名のラベルから外れ値・特異点も確認できる。
| 統計量 | 値 | 解釈 |
|---|---|---|
| Pearson r | −0.682 | 大きな負の相関(Cohen基準: |r|≥0.5 = 大) |
| p 値 | < 0.0001 | 統計的に有意(1%水準でも有意) |
| r²(単相関) | 0.465 | 気温だけで光熱水道費割合の46.5%を説明 |
| サンプルサイズ | n = 47 | 47都道府県(2022年断面) |
光熱費を「金額(万円)」で見るか「消費支出に占める割合(%)」で見るかで、分析の意味が変わる。
金額(万円):地域の物価・所得水準・世帯構成の影響を受けやすい。「東京は光熱費が高い」→ 実は消費総額も高いだけかもしれない。
割合(%):消費支出を分母にすることで「生活費の中での光熱費の重さ」を比較できる。所得水準の差を部分的にコントロールできる。
111 112 113 114 115 116 | fig2, ax2 = plt.subplots(figsize=(9, 7), dpi=150) for region, color in COLOR_MAP.items(): mask = df22['地域区分'] == region ax2.scatter(df22.loc[mask, COL_TEMP], df22.loc[mask, '光熱水道費割合'], color=color, s=70, zorder=3, label=region, alpha=0.85, edgecolors='white', linewidth=0.8) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。117 118 119 120 121 122 123 | # 都道府県ラベル(全都道府県) for _, row in df22.iterrows(): pref_short = row[COL_PREF].replace('県', '').replace('都', '').replace('道', '').replace('府', '') ax2.annotate(pref_short, (row[COL_TEMP], row['光熱水道費割合']), xytext=(3, 3), textcoords='offset points', fontsize=6.5, color='#333', zorder=4) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。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 | # 回帰直線 x_reg = df22[COL_TEMP].values y_reg = df22['光熱水道費割合'].values slope, intercept, r_val, p_val, se = stats.linregress(x_reg, y_reg) x_line = np.linspace(x_reg.min(), x_reg.max(), 100) ax2.plot(x_line, slope * x_line + intercept, color='#C62828', linewidth=1.8, linestyle='-', zorder=2, label=f'回帰直線 (r={r_val:.3f}, p={p_val:.4f})') ax2.set_xlabel('年平均気温(℃)', fontsize=12) ax2.set_ylabel('光熱水道費割合(%)', fontsize=12) ax2.set_title('図2 年平均気温 vs 光熱水道費割合(2022年、47都道府県)\n' '気温が低い地域ほど家計に占める光熱費の割合が高い', fontsize=11, fontweight='bold', pad=12) ax2.text(0.97, 0.97, f'r = {r_val:.3f}\np = {p_val:.4f}', transform=ax2.transAxes, ha='right', va='top', fontsize=10, bbox=dict(boxstyle='round,pad=0.4', facecolor='#FFF9C4', alpha=0.9)) ax2.legend(fontsize=9, loc='upper right') ax2.grid(alpha=0.3) ax2.spines['top'].set_visible(False) ax2.spines['right'].set_visible(False) fig2.tight_layout() fig2_path = os.path.join(FIG_DIR, '2022_H5_8_fig2_scatter.png') fig2.savefig(fig2_path, dpi=150, bbox_inches='tight') plt.close(fig2) print(f"図2 保存: {fig2_path}") |
findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: …(長いため省略)
stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。単純な気温との相関分析に加え、複数の要因(年平均気温・最高気温・最低気温・高齢化率・消費支出)を同時に投入した OLS 重回帰を行う。説明変数は全て標準化し、回帰係数の相対的な大きさ(β係数)を比較する。
| 説明変数 | β係数(標準化) | p 値 | 解釈 |
|---|---|---|---|
| 年平均気温(℃) | −1.898 | 0.004 | 気温↑ → 光熱費割合↓(有意) |
| 消費支出(対数) | −0.463 | 0.001 | 消費水準↑ → 割合↓(富裕地域は割合小) |
| 最低気温(℃) | +0.967 | 0.047 | 冬の最低気温↑ → 暖房費↑(やや有意) |
| 高齢化率(%) | +0.170 | 0.232 | 高齢化 → 光熱費増(有意でない) |
| 最高気温(℃) | +0.155 | 0.567 | 夏の高温 → 冷房費(有意でない) |
連続変数(気温)に加え、「寒冷地ダミー」「温暖地ダミー」のようなカテゴリ変数を回帰に加えることで、気候帯特有の構造的差異をコントロールできる。
たとえば北海道は特別な暖房インフラ(集中暖房・灯油暖房)を持ち、気温だけでは説明できない固有の光熱費構造がある。地域ダミーはこのような「暗黙の差異」を吸収する。
152 153 154 155 156 157 158 159 160 161 | var_labels = { COL_TEMP: '年平均気温(℃)', '最高気温': '最高気温(℃)', '最低気温': '最低気温(℃)', '高齢化率': '高齢化率(%)', '消費支出_log': '消費支出(対数)', } X_cols = list(var_labels.keys()) X_data = df22[X_cols].copy() y_data = df22['光熱水道費割合'].copy() |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | # 欠損除去 valid = X_data.notna().all(axis=1) & y_data.notna() X_data = X_data[valid] y_data = y_data[valid] # 標準化(β係数のプロット用) X_std = (X_data - X_data.mean()) / X_data.std() X_const = sm.add_constant(X_std) model = sm.OLS(y_data, X_const).fit() print("\nOLS 回帰結果:") print(model.summary()) coefs = model.params[1:] # 定数項除く ci_low = model.conf_int().iloc[1:, 0] ci_hi = model.conf_int().iloc[1:, 1] pvals = model.pvalues[1:] labels = [var_labels[c] for c in X_cols] |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。sm.add_constant(X) — 切片項(定数1の列)を先頭に追加。statsmodelsで必須。sm.OLS(y, X).fit() — 最小二乗法でモデルを推定。model.params, model.pvalues, model.conf_int() で結果取得。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | # 係数の大きい順にソート order = np.argsort(np.abs(coefs.values))[::-1] coefs_s = coefs.values[order] ci_low_s = ci_low.values[order] ci_hi_s = ci_hi.values[order] pvals_s = pvals.values[order] labels_s = [labels[i] for i in order] fig3, ax3 = plt.subplots(figsize=(8, 5), dpi=150) colors3 = ['#1565C0' if c < 0 else '#E65100' for c in coefs_s] sig_marker = ['*' if p < 0.05 else '' for p in pvals_s] y_pos = np.arange(len(labels_s)) ax3.barh(y_pos, coefs_s, color=colors3, alpha=0.75, height=0.55, zorder=3) ax3.errorbar(coefs_s, y_pos, xerr=[coefs_s - ci_low_s, ci_hi_s - coefs_s], fmt='none', color='#333', capsize=4, linewidth=1.2, zorder=4) ax3.axvline(0, color='#333', linewidth=1, linestyle='-') ax3.set_yticks(y_pos) ax3.set_yticklabels([f'{lbl} {mk}' for lbl, mk in zip(labels_s, sig_marker)], fontsize=10) ax3.set_xlabel('標準化回帰係数(β)', fontsize=11) ax3.set_title(f'図3 OLS 回帰係数プロット(光熱水道費割合の決定要因)\n' f'目的変数: 光熱水道費割合(%) R² = {model.rsquared:.3f} n=47', fontsize=10, fontweight='bold', pad=10) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。202 203 204 205 206 207 208 209 210 211 212 213 214 215 | # * 凡例 ax3.text(0.98, 0.02, '* p<0.05 青=負の効果 橙=正の効果\n95%信頼区間を横棒で表示', transform=ax3.transAxes, ha='right', va='bottom', fontsize=9, bbox=dict(boxstyle='round,pad=0.3', facecolor='#F8F9FA', alpha=0.9)) ax3.grid(axis='x', alpha=0.3) ax3.spines['top'].set_visible(False) ax3.spines['right'].set_visible(False) fig3.tight_layout() fig3_path = os.path.join(FIG_DIR, '2022_H5_8_fig3_coef.png') fig3.savefig(fig3_path, dpi=150, bbox_inches='tight') plt.close(fig3) print(f"図3 保存: {fig3_path}") |
OLS 回帰結果:
OLS Regression Results
==============================================================================
Dep. Variable: 光熱水道費割合 R-squared: 0.736
Model: OLS Adj. R-squared: 0.704
Method: Least Squares F-statistic: 22.88
Date: Mon, 18 May 2026 Prob (F-statistic): 6.78e-11
Time: 11:24:12 Log-Likelihood: -47.702
No. Observations: 47 AIC: 107.4
Df Residuals: 41 BIC: 118.5
Df Model: 5
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 8.7074 0.104 83.510 0.000 8.497 8.918
年平均気温 -1.8981 0.618 -3.071 0.004 -3.146 -0.650
最高気温 0.1550 0.269 0.577 0.567 -0.388 0.698
最低気温 0.9666 0.472 2.046 0.047 0.012 1.921
高齢化率 0.1699 0.140 1.213 0.232 -0.113 0.453
消費支出_log -0.4633 0.136 -3.405 0.001 -0.738 -0.189
==============================================================================
Omnibus: 0.430 Durbin-Watson: 1.696
Prob(Omnibus): 0.807 Jarque-Bera (JB): 0.055
Skew: -0.051 Prob(JB): 0.973
Kurtosis: 3.133 Cond. No. 12.4
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not found.
findfont: Font family 'Noto Sans CJK JP' not found.
findfont: Font family 'Hiragino Kaku Gothic ProN' not
…(長いため省略)x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。断面分析(2022年)だけでなく、2012〜2023年の時系列でも寒冷地と温暖地の差異が安定して存在するかを確認する。2021〜2022年のエネルギー価格急騰が光熱費に与えた影響にも注目する。
本分析の「気温 → 光熱費」の関係式は、気候変動シナリオと組み合わせることで将来の家計負担予測に活用できる。
例:IPCC の温暖化シナリオ(SSP2-4.5)では、2100年に向けて日本の年平均気温が約2〜3℃上昇すると予測される。回帰係数(β = −1.898)を用いれば、「気温が2℃上昇すれば光熱水道費割合が約3.8ポイント低下する」という粗い試算が可能。ただし将来の予測には不確実性が大きく、複数シナリオの検討が必要。
217 218 219 220 221 222 223 224 225 226 227 228 229 | years_avail = sorted(df[COL_YEAR].unique()) # 地域区分ごとの年次平均を計算 ts = df.groupby([COL_YEAR, '地域区分']).agg( 光熱水道費_万円=('光熱水道費_万円', 'mean'), 光熱水道費割合=('光熱水道費割合', 'mean') ).reset_index() ts_k = ts[ts['地域区分'] == '寒冷地'].sort_values(COL_YEAR) ts_o = ts[ts['地域区分'] == '温暖地'].sort_values(COL_YEAR) ts_s = ts[ts['地域区分'] == 'その他'].sort_values(COL_YEAR) fig4, (ax4a, ax4b) = plt.subplots(1, 2, figsize=(12, 5), dpi=150) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | # 左:光熱水道費_万円 ax4a.plot(ts_k[COL_YEAR], ts_k['光熱水道費_万円'], 'o-', color='#1565C0', linewidth=2, markersize=5, label='寒冷地(北海道・東北)') ax4a.plot(ts_o[COL_YEAR], ts_o['光熱水道費_万円'], 's-', color='#E65100', linewidth=2, markersize=5, label='温暖地(九州・四国南部)') ax4a.plot(ts_s[COL_YEAR], ts_s['光熱水道費_万円'], '^--', color='#78909C', linewidth=1.5, markersize=4, label='その他') ax4a.set_xlabel('年度', fontsize=10) ax4a.set_ylabel('光熱水道費(万円)', fontsize=10) ax4a.set_title('光熱水道費の推移(万円)', fontsize=11, fontweight='bold') ax4a.legend(fontsize=8) ax4a.grid(alpha=0.3) ax4a.spines['top'].set_visible(False) ax4a.spines['right'].set_visible(False) ax4a.set_xticks(years_avail) ax4a.set_xticklabels([str(y) for y in years_avail], rotation=45, fontsize=8) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | # 右:光熱水道費割合 ax4b.plot(ts_k[COL_YEAR], ts_k['光熱水道費割合'], 'o-', color='#1565C0', linewidth=2, markersize=5, label='寒冷地(北海道・東北)') ax4b.plot(ts_o[COL_YEAR], ts_o['光熱水道費割合'], 's-', color='#E65100', linewidth=2, markersize=5, label='温暖地(九州・四国南部)') ax4b.plot(ts_s[COL_YEAR], ts_s['光熱水道費割合'], '^--', color='#78909C', linewidth=1.5, markersize=4, label='その他') ax4b.set_xlabel('年度', fontsize=10) ax4b.set_ylabel('光熱水道費割合(%)', fontsize=10) ax4b.set_title('消費支出に占める光熱水道費割合の推移', fontsize=11, fontweight='bold') ax4b.legend(fontsize=8) ax4b.grid(alpha=0.3) ax4b.spines['top'].set_visible(False) ax4b.spines['right'].set_visible(False) ax4b.set_xticks(years_avail) ax4b.set_xticklabels([str(y) for y in years_avail], rotation=45, fontsize=8) fig4.suptitle('図4 光熱水道費の時系列推移:寒冷地 vs 温暖地(2012〜2023年)', fontsize=12, fontweight='bold', y=1.02) fig4.tight_layout() fig4_path = os.path.join(FIG_DIR, '2022_H5_8_fig4_timeseries.png') fig4.savefig(fig4_path, dpi=150, bbox_inches='tight') plt.close(fig4) print(f"図4 保存: {fig4_path}") print("\n全図の保存完了。") print(f"出力先: {os.path.abspath(FIG_DIR)}") |
findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: Font family 'Noto Sans CJK JP' not found. findfont: Font family 'Hiragino Kaku Gothic ProN' not found. findfont: …(長いため省略)
x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。SSDSE-B(47都道府県、2022年)のデータを用いた統計分析の結果、以下が明らかになった:
| データ | 出典 |
|---|---|
| SSDSE-B 都道府県データ(2012〜2023年) | 統計数理研究所 SSDSE(社会・人口統計体系) |
| 年平均気温・最高気温・最低気温 | SSDSE-B(出典:気象庁 気象統計情報) |
| 光熱・水道費・消費支出(二人以上の世帯) | SSDSE-B(出典:総務省 家計調査) |
| 65歳以上人口・総人口 | SSDSE-B(出典:総務省 人口推計) |
本教育用コードは SSDSE-B-2026.csv の実データのみを使用。合成データ(np.random.seed等)は一切使用していない。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。