このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
2050年カーボンニュートラルの達成に向けて、日本全国1739市区町村の CO₂ 削減状況には大きな地域差が存在する。 部門別(製造業・業務・家庭・運輸・農林水産業)の排出量を分析することで、各自治体が抱える課題の「タイプ」を把握し、 効果的な対策の類型化が可能になる。
まず「CO₂排出特性による市区町村の類型化と地域特性の関係」を統計的にとらえることが有効だと考えられる。 その理由は感覚や経験則だけでは、複雑な社会要因の中で「何が本当に効いているか」を見極めにくいからである。 本研究では公開データと統計手法を組み合わせ、この問いに定量的な答えを出すことを目指す。
この研究は、環境省「部門別CO₂排出量現況推計」(2017・2022年)を用い、 修正ウィーバー法(Modified Weaver Method)により各市区町村を部門特性で類型化したうえで、 農業地域類型・気候区分・人口密度などの地域特性との関係を統計的に明らかにしている。
| データ | 出典 | 使用変数 |
|---|---|---|
| 部門別CO₂排出量現況推計 | 環境省 | 製造業・業務・家庭・運輸・農林水産業 部門別排出量(2017・2022年) |
| 農業地域類型 | 農林水産省 | 都市的地域・平地農業・中間農業・山間農業 |
| 省エネ地域区分 | 国土交通省 | 気候条件(1〜8区:1=最寒冷・8=最温暖) |
| SSDSE-A(市区町村版) | 統計センター | 人口・財政力指数・可住地人口密度 |
| カテゴリー | 変数 | 説明 |
|---|---|---|
| 目的変数 | CO₂削減量(部門別) | 2022年 − 2017年(正 = 削減) |
| CO₂削減率 | (2017年 − 2022年)/ 2017年 | |
| 説明変数 | 農業地域類型 | 都市的・平地農業・中間農業・山間農業 |
| 省エネ地域区分 | 1〜8区(気候条件の代理変数) | |
| 可住地人口密度 | 人/km²(都市化の指標) | |
| 産業特化係数(LQ) | 製造業の全国比シェア |
1 2 3 4 5 6 7 8 9 10 | import os 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.gridspec import GridSpec import warnings warnings.filterwarnings('ignore') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。matplotlib.use('Agg') — グラフを画面表示せずファイルに保存するためのおまじない。f"...{x}..." はf-string。文字列の中に {変数} と書くだけで埋め込めて、{x:.2f} のように書式も指定できます。11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # ── パス設定 ───────────────────────────────────────────────────────────────── FIG_DIR = 'html/figures' DATA_DIR = 'data/raw' os.makedirs(FIG_DIR, exist_ok=True) plt.rcParams.update({ 'font.family': 'Hiragino Sans', 'axes.unicode_minus': False, 'figure.dpi': 150, 'axes.spines.top': False, 'axes.spines.right': False, }) print("=" * 65) print("■ SSDSE-E-2026 実データ読み込み") print("=" * 65) df_e_raw = pd.read_csv(os.path.join(DATA_DIR, 'SSDSE-E-2026.csv'), encoding='cp932') df_e = df_e_raw.iloc[2:].copy() df_e.columns = df_e_raw.iloc[1].values df_e = df_e[df_e['都道府県'] != '全国'].reset_index(drop=True) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。os.makedirs('html/figures', exist_ok=True) — 図の保存先フォルダを作る(既にあってもOK)。pd.read_csv(...) でCSVを読み込みます。encoding='cp932' は日本語Windows由来の文字コード、header=1 は「2行目を列名として使う」。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。32 33 34 35 36 37 38 39 40 41 42 43 44 45 | # 数値変換 num_cols_e = [ '総人口', 'ごみ総排出量(総量)', '1人1日当たりの排出量', 'ごみのリサイクル率', '農家数(販売農家)', '1人当たり県民所得(平成27年基準)', '総面積(北方地域及び竹島を除く)', '大型小売店数', '飲食店数', '医師数', '事業所数(民営)(製造業)', '事業所数(民営)(建設業)', ] for c in num_cols_e: df_e[c] = pd.to_numeric(df_e[c], errors='coerce') print(f" 読み込み完了: {len(df_e)} 都道府県") print(f" 主要変数確認:") print(f" ごみ総排出量(総量)[t]: {df_e['ごみ総排出量(総量)'].describe().loc[['mean','min','max']].round(0).to_dict()}") print(f" ごみのリサイクル率[%]: {df_e['ごみのリサイクル率'].describe().loc[['mean','min','max']].round(1).to_dict()}") |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.describe() — 件数・平均・標準偏差・四分位・最大/最小を一括計算。データの素性チェックに必須。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。46 47 48 49 50 51 52 | # ── 指標の計算 ───────────────────────────────────────────────────────────── # 農家率(農家数 / 総人口 × 1000) df_e['農家率'] = df_e['農家数(販売農家)'] / df_e['総人口'] * 1000 # 人口密度 (人/km²) — 面積はha単位なので÷100でkm² df_e['人口密度'] = df_e['総人口'] / (df_e['総面積(北方地域及び竹島を除く)'] / 100) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。53 54 55 56 57 58 59 60 | # 商業活動指数(飲食店数 + 大型小売店数 の人口千対) df_e['商業活動指数'] = (df_e['飲食店数'] + df_e['大型小売店数']) / df_e['総人口'] * 1000 # 医師数10万対 df_e['医師数10万対'] = df_e['医師数'] / df_e['総人口'] * 100000 # 製造業事業所率(製造業事業所 / 全事業所) df_e['製造業率'] = df_e['事業所数(民営)(製造業)'] / (df_e['事業所数(民営)(製造業)'] + df_e['事業所数(民営)(建設業)'] + 1) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。61 62 63 64 65 66 | # ── ウィーバー法用の4部門シェア計算 ─────────────────────────────────────── # 廃棄物・環境の視点から4つの活動軸を定義: # 1. ごみ排出(ごみ総排出量 → 都道府県シェア) # 2. リサイクル(ごみのリサイクル率) # 3. 農業活動(農家率) # 4. 商業活動(商業活動指数) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。67 68 69 70 71 72 73 74 75 76 77 | # 各軸を全都道府県合計に対する%シェアに変換 def to_share_pct(series): """シリーズを全都道府県の合計に対する%シェアに変換""" total = series.sum() return (series / total * 100).values # 4部門シェア(合計は各部門の合計シェア=100になるよう正規化) waste_share = to_share_pct(df_e['ごみ総排出量(総量)']) recycle_share = to_share_pct(df_e['ごみのリサイクル率']) agri_share = to_share_pct(df_e['農家率']) commerce_share = to_share_pct(df_e['商業活動指数']) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。78 79 80 81 82 83 84 85 86 | # 各都道府県の4部門比率(行合計が100%) shares_matrix = np.column_stack([ waste_share, recycle_share, agri_share, commerce_share ]) # 各都道府県内で行合計を100に正規化 row_sums = shares_matrix.sum(axis=1, keepdims=True) shares_pct = shares_matrix / row_sums * 100 # shape: (47, 4) SECTORS = ['廃棄物排出', 'リサイクル', '農業活動', '商業活動'] |
=================================================================
■ SSDSE-E-2026 実データ読み込み
=================================================================
読み込み完了: 47 都道府県
主要変数確認:
ごみ総排出量(総量)[t]: {'mean': 829240.0, 'min': 190681.0, 'max': 4046316.0}
ごみのリサイクル率[%]: {'mean': 18.1, 'min': 11.9, 'max': 29.0}s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | def modified_weaver(shares_arr): """ shares_arr: 1次元array、各部門の百分率シェア(合計100) 戻り値 : (k_opt, dominant_idx) k_opt 最適なk(複合類型の次元数) dominant_idx 最大シェア部門のインデックス """ n = len(shares_arr) sorted_idx = np.argsort(shares_arr)[::-1] # 降順インデックス sorted_sh = shares_arr[sorted_idx] best_k = 1 best_w = np.inf for k in range(1, n + 1): top_k = sorted_sh[:k] equal = 100.0 / k w_k = np.sum((top_k - equal) ** 2) if w_k < best_w: best_w = w_k best_k = k dominant = sorted_idx[0] return best_k, dominant print("\n" + "=" * 65) print("■ 修正ウィーバー法による都道府県類型化") print("=" * 65) dominant_idx = np.array([modified_weaver(shares_pct[i])[1] for i in range(47)]) dominant_k = np.array([modified_weaver(shares_pct[i])[0] for i in range(47)]) weaver_type = np.array([SECTORS[d] + '型' for d in dominant_idx]) df_e['ウィーバー類型'] = weaver_type df_e['ウィーバーk'] = dominant_k |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df['A'] / df['B'] — pandasの列同士の四則演算は要素ごと(element-wise)。forループ不要なのが強み。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 | # ── 人口密度区分(地域類型の代理) ─────────────────────────────────────────── density_q33 = df_e['人口密度'].quantile(0.33) density_q67 = df_e['人口密度'].quantile(0.67) def density_group(d): if d >= density_q67: return '高密度(都市部)' elif d >= density_q33: return '中密度(地方中核)' else: return '低密度(農村・山間)' df_e['密度区分'] = df_e['人口密度'].apply(density_group) type_counts = df_e['ウィーバー類型'].value_counts() print(f"\n総観測数: 47 都道府県") print(f"\n【ウィーバー類型の分布】") for t, c in type_counts.items(): print(f" {t:<14} {c:>3}都道府県 ({c/47*100:.1f}%)") print(f"\n【密度区分 × ウィーバー類型のクロス集計(行%)】") ct = pd.crosstab(df_e['密度区分'], df_e['ウィーバー類型'], normalize='index').round(3) print(ct * 100) print(f"\n【リサイクル率の記述統計】") print(df_e['ごみのリサイクル率'].describe().round(2)) |
================================================================= ■ 修正ウィーバー法による都道府県類型化 ================================================================= 総観測数: 47 都道府県 【ウィーバー類型の分布】 農業活動型 21都道府県 (44.7%) 廃棄物排出型 11都道府県 (23.4%) 商業活動型 8都道府県 (17.0%) リサイクル型 7都道府県 (14.9%) 【密度区分 × ウィーバー類型のクロス集計(行%)】 ウィーバー類型 リサイクル型 商業活動型 廃棄物排出型 農業活動型 密度区分 中密度(地方中核) 33.3 26.7 0.0 40.0 低密度(農村・山間) 0.0 12.5 6.2 81.2 高密度(都市部) 12.5 12.5 62.5 12.5 【リサイクル率の記述統計】 count 47.00 mean 18.07 std 4.19 min 11.90 25% 15.10 50% 17.10 75% 21.00 max 29.00 Name: ごみのリサイクル率, dtype: float64
.describe() — 件数・平均・標準偏差・四分位・最大/最小を一括計算。データの素性チェックに必須。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。148 149 150 151 152 153 154 | mfg_share_pref = df_e['事業所数(民営)(製造業)'] / ( df_e['事業所数(民営)(製造業)'] + df_e['事業所数(民営)(建設業)'] ) mfg_nat_share = mfg_share_pref.mean() df_e['LQ製造業'] = mfg_share_pref / mfg_nat_share print(f"\n 製造業LQ: 平均={df_e['LQ製造業'].mean():.3f}, 最大={df_e['LQ製造業'].max():.3f} ({df_e.loc[df_e['LQ製造業'].idxmax(), '都道府県']})") |
製造業LQ: 平均=1.000, 最大=1.337 (大阪府)
.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | print("\n" + "=" * 65) print("✓ 全図の生成完了(4枚)") print("=" * 65) print("\n【最終サマリー】") print(f"\n データ: SSDSE-E-2026 実公的データ(47都道府県)") print(f" 全体リサイクル率平均: {df_e['ごみのリサイクル率'].mean():.1f}%") print(f" 1人1日排出量平均: {df_e['1人1日当たりの排出量'].mean():.0f} g") print(f"\n ウィーバー類型別リサイクル率(平均):") for t in TYPE_ORDER: sub = df_e[df_e['ウィーバー類型'] == t] m = sub['ごみのリサイクル率'].mean() n = len(sub) print(f" {t:<14} {m:.1f}% (n={n})") print(f"\n 製造業LQトップ5:") top5 = df_e.nlargest(5, 'LQ製造業')[['都道府県', 'LQ製造業', 'ごみのリサイクル率']] for _, row in top5.iterrows(): print(f" {row['都道府県']}: LQ={row['LQ製造業']:.2f}, リサイクル率={row['ごみのリサイクル率']:.1f}%") |
=================================================================
✓ 全図の生成完了(4枚)
=================================================================
【最終サマリー】
データ: SSDSE-E-2026 実公的データ(47都道府県)
全体リサイクル率平均: 18.1%
1人1日排出量平均: 878 g
ウィーバー類型別リサイクル率(平均):
廃棄物排出型 20.7% (n=11)
リサイクル型 20.5% (n=7)
農業活動型 17.0% (n=21)
商業活動型 15.2% (n=8)
製造業LQトップ5:
大阪府: LQ=1.34, リサイクル率=12.6%
京都府: LQ=1.32, リサイクル率=14.6%
岐阜県: LQ=1.26, リサイクル率=17.1%
愛知県: LQ=1.24, リサイクル率=22.0%
奈良県: LQ=1.23, リサイクル率=15.7%for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。まず市区町村ごとに「どの部門が主導してCO₂を排出しているか」を機械的に判定することが有効だと考えられる。 その理由は製造業中心の自治体と家庭排出が中心の自治体では、削減すべき対象も施策も全く異なるからである。 ここでは複数部門のシェアの「ばらつき」に着目し、修正ウィーバー法という地理学の類型化手法を用いる。 自治体を5タイプに分類でき、タイプごとに異なる削減特性が見える結果が期待される。
ウィーバー法(Weaver Method)は、地理学・産業分析で使われる 地域の複合特性を「何の組み合わせが最も代表的か」を数値的に決定する手法。 1954年にJ.C. Weaverが農業地域の複合類型化に提案し、後に 修正ウィーバー法(Modified Weaver Method)として一般化された。
各市区町村で W_k を全 k について計算し、最小値を与える k を求める。
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | print("\n図1: ウィーバー類型別環境指標グラフを作成中...") fig1, axes1 = plt.subplots(1, 2, figsize=(13, 5)) fig1.suptitle('修正ウィーバー法による類型化と廃棄物・環境特性\n(実データ:SSDSE-E-2026)', fontsize=13, fontweight='bold') # (a) 類型別リサイクル率(平均±SD) ax = axes1[0] means_rc = [df_e[df_e['ウィーバー類型'] == t]['ごみのリサイクル率'].mean() for t in TYPE_ORDER] stds_rc = [df_e[df_e['ウィーバー類型'] == t]['ごみのリサイクル率'].std() for t in TYPE_ORDER] colors = [TYPE_COLORS.get(t, '#888') for t in TYPE_ORDER] x = np.arange(len(TYPE_ORDER)) bars = ax.bar(x, means_rc, yerr=stds_rc, capsize=6, color=colors, alpha=0.85, edgecolor='white', error_kw={'elinewidth': 1.5}) ax.axhline(df_e['ごみのリサイクル率'].mean(), color='gray', linestyle='--', linewidth=1.2, label=f'全体平均 ({df_e["ごみのリサイクル率"].mean():.1f}%)') ax.set_xticks(x) ax.set_xticklabels(TYPE_ORDER, fontsize=10) ax.set_ylabel('ごみのリサイクル率(%)', fontsize=11) ax.set_title('ウィーバー類型別 リサイクル率\n(平均±1SD)', fontsize=11, fontweight='bold') ax.legend(fontsize=9) ax.grid(axis='y', alpha=0.3) for i, (m, s) in enumerate(zip(means_rc, stds_rc)): n_type = (df_e['ウィーバー類型'] == TYPE_ORDER[i]).sum() ax.text(i, m + (s if not np.isnan(s) else 0) + 0.5, f'{m:.1f}%\n(n={n_type})', ha='center', fontsize=8.5, fontweight='bold') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | # (b) 密度区分別の1人1日当たり排出量(ボックスプロット) ax2 = axes1[1] data_by_density = [df_e[df_e['密度区分'] == d]['1人1日当たりの排出量'].values for d in DENSITY_ORDER] bp = ax2.boxplot(data_by_density, patch_artist=True, notch=False, widths=0.55) dp_colors = [DENSITY_COLORS[d] for d in DENSITY_ORDER] for patch, color in zip(bp['boxes'], dp_colors): patch.set_facecolor(color) patch.set_alpha(0.75) for med in bp['medians']: med.set(color='white', linewidth=2) ax2.set_xticklabels(['高密度\n(都市部)', '中密度\n(地方中核)', '低密度\n(農村・山間)'], fontsize=9) ax2.set_ylabel('1人1日当たりの排出量(g)', fontsize=11) ax2.set_title('人口密度区分別\n1人1日当たりごみ排出量分布', fontsize=11, fontweight='bold') ax2.grid(axis='y', alpha=0.3) ax2.axhline(df_e['1人1日当たりの排出量'].mean(), color='gray', linestyle='--', linewidth=1.0) plt.tight_layout() fig1.savefig(os.path.join(FIG_DIR, '2025_U5_1_fig1_co2_bar.png'), bbox_inches='tight', dpi=150) plt.close(fig1) print(" → 2025_U5_1_fig1_co2_bar.png 保存完了") |
図1: ウィーバー類型別環境指標グラフを作成中... → 2025_U5_1_fig1_co2_bar.png 保存完了
ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。
| ウィーバー類型 | 市区町村数 | CO₂削減率 平均 | 主な地域特性 |
|---|---|---|---|
| 製造業型 | 〜 450 | 13〜16% | 工業地帯・平地農業・臨海部 |
| 業務型 | 〜 380 | 12〜15% | 都市的地域・商業集積地 |
| 家庭型 | 〜 420 | 10〜13% | 都市的地域・ベッドタウン(削減が遅れ) |
| 運輸型 | 〜 280 | 14〜17% | 広域農村・中間農業・車依存地域 |
| 農林水産業型 | 〜 210 | 15〜19% | 山間農業・漁業地域(削減が顕著) |
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | print("図2: クロス集計ヒートマップを作成中...") ct_abs = pd.crosstab(df_e['密度区分'], df_e['ウィーバー類型']) # 存在する列のみ使う type_order_exist = [t for t in TYPE_ORDER if t in ct_abs.columns] density_order_exist = [d for d in DENSITY_ORDER if d in ct_abs.index] ct_abs = ct_abs.reindex(index=density_order_exist, columns=type_order_exist, fill_value=0) ct_row = ct_abs.div(ct_abs.sum(axis=1), axis=0) * 100 fig2, axes2 = plt.subplots(1, 2, figsize=(13, 5)) fig2.suptitle('人口密度区分 × ウィーバー類型 クロス集計\n(実データ:SSDSE-E-2026, 47都道府県)', fontsize=13, fontweight='bold') for ax, data, title, fmt in zip( axes2, [ct_abs, ct_row], ['実数(都道府県数)', '行%(密度区分別の構成比)'], ['.0f', '.1f'], ): im = ax.imshow(data.values, cmap='Blues', aspect='auto') ax.set_xticks(range(len(type_order_exist))) ax.set_yticks(range(len(density_order_exist))) ax.set_xticklabels(type_order_exist, fontsize=10, rotation=20, ha='right') ax.set_yticklabels(density_order_exist, fontsize=10) ax.set_title(title, fontsize=11, fontweight='bold') for i in range(len(density_order_exist)): for j in range(len(type_order_exist)): val = data.values[i, j] max_val = data.values.max() text_color = 'white' if (max_val > 0 and val > max_val * 0.6) else 'black' ax.text(j, i, f'{val:{fmt}}', ha='center', va='center', fontsize=9, fontweight='bold', color=text_color) plt.colorbar(im, ax=ax, shrink=0.85) plt.tight_layout() fig2.savefig(os.path.join(FIG_DIR, '2025_U5_1_fig2_crosstab.png'), bbox_inches='tight', dpi=150) plt.close(fig2) print(" → 2025_U5_1_fig2_crosstab.png 保存完了") |
図2: クロス集計ヒートマップを作成中... → 2025_U5_1_fig2_crosstab.png 保存完了
fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。前節の類型別にCO₂削減率の平均が異なる結果を踏まえると、 排出構造の違いだけでなく、気候や地理など外的要因も削減率を左右する可能性が背景にあると考えられる。 これを検証する必要があるが、その手法として類型×気候区分のクロス集計に着目した。 寒冷地・温暖地で同じ類型でも削減率が異なる結果が期待される。
2つのカテゴリ変数の組み合わせで集計する。normalize='index' で行% を計算。
省エネ地域区分(1〜8区)と CO₂ 削減率の関係を見ると、 寒冷地(区分 1〜3)の自治体では製造業・農林水産業部門の削減が大きい。 これは産業構造の変化(脱炭素化設備投資)だけでなく、 省エネ補助制度の活用が冬季暖房需要の多い寒冷地で進んでいるためと考えられる。
| 省エネ地域区分 | 気候特性 | CO₂削減率(参考) | 特徴 |
|---|---|---|---|
| 1〜3区 | 寒冷・亜寒帯 | 16〜19%(高) | 暖房需要大→省エネ効果が顕著 |
| 4〜5区 | 温帯(内陸) | 13〜16%(中) | 製造業比率が高く設備更新効果 |
| 6〜8区 | 温暖・亜熱帯 | 10〜13%(低) | 都市的地域多く家庭・業務削減が遅れ |
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | print("図3: 産業特化係数×環境指標散布図を作成中...") fig3, axes3 = plt.subplots(1, 2, figsize=(13, 5)) fig3.suptitle('産業特化係数(製造業)と廃棄物・環境指標\n(実データ:SSDSE-E-2026)', fontsize=13, fontweight='bold') # (a) LQ vs リサイクル率(密度区分で色分け) ax3a = axes3[0] for d, col in DENSITY_COLORS.items(): mask = df_e['密度区分'] == d ax3a.scatter(df_e.loc[mask, 'LQ製造業'], df_e.loc[mask, 'ごみのリサイクル率'], color=col, alpha=0.75, s=60, label=d, zorder=3) # 都道府県名をラベル(LQ極値のみ) for _, row in df_e[mask].iterrows(): if row['LQ製造業'] > 1.3 or row['LQ製造業'] < 0.6: ax3a.annotate(row['都道府県'][:2], (row['LQ製造業'], row['ごみのリサイクル率']), fontsize=7, ha='left', va='bottom', color='#333') ax3a.axvline(1.0, color='gray', linestyle='--', linewidth=1.0, label='LQ=1(全国平均)') ax3a.set_xlabel('製造業の産業特化係数(LQ)', fontsize=11) ax3a.set_ylabel('ごみのリサイクル率(%)', fontsize=11) ax3a.set_title('LQ(製造業)vs リサイクル率\n(人口密度区分別)', fontsize=11, fontweight='bold') ax3a.legend(fontsize=8, markerscale=1.5) ax3a.grid(True, alpha=0.2) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。ax.axhline / ax.axvline — 水平/垂直の点線。平均線や基準線として定番。for _, row in df.iterrows() — DataFrameを1行ずつ取り出すループ。1点ずつ描画したいときに使用。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。286 287 288 289 290 291 292 293 | # 回帰直線 lq_vals = df_e['LQ製造業'].values rc_vals = df_e['ごみのリサイクル率'].values coef = np.polyfit(lq_vals, rc_vals, 1) x_range = np.linspace(lq_vals.min(), lq_vals.max(), 100) ax3a.plot(x_range, np.polyval(coef, x_range), color='black', linewidth=1.5, linestyle='-', label=f'回帰直線 (β={coef[0]:+.2f})', zorder=2) ax3a.legend(fontsize=8, markerscale=1.5) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | # (b) ウィーバー類型別の4部門平均シェア(積み上げ棒グラフ) ax3b = axes3[1] sector_colors_list = ['#1565C0', '#2E7D32', '#E65100', '#6A1B9A'] bottom = np.zeros(len(TYPE_ORDER)) for i, s in enumerate(SECTORS): means_s = [shares_pct[df_e['ウィーバー類型'] == t, i].mean() for t in TYPE_ORDER] ax3b.bar(np.arange(len(TYPE_ORDER)), means_s, bottom=bottom, color=sector_colors_list[i], label=s, alpha=0.85, edgecolor='white') bottom += np.array(means_s) ax3b.set_xticks(np.arange(len(TYPE_ORDER))) ax3b.set_xticklabels(TYPE_ORDER, fontsize=9, rotation=15, ha='right') ax3b.set_ylabel('4部門平均シェア(%)', fontsize=11) ax3b.set_title('ウィーバー類型別 部門構成比\n(廃棄物・農業・商業活動軸)', fontsize=11, fontweight='bold') ax3b.legend(fontsize=9, loc='upper right') ax3b.grid(axis='y', alpha=0.3) plt.tight_layout() fig3.savefig(os.path.join(FIG_DIR, '2025_U5_1_fig3_lq.png'), bbox_inches='tight', dpi=150) plt.close(fig3) print(" → 2025_U5_1_fig3_lq.png 保存完了") |
図3: 産業特化係数×環境指標散布図を作成中... → 2025_U5_1_fig3_lq.png 保存完了
np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。前節の類型と気候の交差で削減特性が異なる結果を踏まえると、 「製造業型」と一口に言っても、地域の産業特化の度合いで削減ポテンシャルが変わると考えられる。 これを検証する必要があるが、その手法として産業特化係数(Location Quotient, LQ)に着目した。 全国平均と比較した特化の強さで自治体を細分化でき、より精度の高い政策提言が可能になる結果が期待される。
産業特化係数(Location Quotient: LQ)とは、 ある地域の特定産業の「特化度」を全国比で示す指標。
製造業の LQ が高い自治体ほど、製造業部門の脱炭素化(設備更新・エネルギー転換)の影響が CO₂ 削減率に強く現れる。一方、LQ が低い都市的・農業地域では、 家庭・業務・運輸部門の対策が削減の鍵となる。
地域の特化度を全国比で評価する。各地域の「相対的な産業比重」を明らかにできる。
318 319 320 321 322 323 324 325 326 327 | print("図4: ウィーバー法説明図を作成中...") # 代表的な都道府県を選ぶ(LQ高い=製造業特化) top_mfg_pref_idx = df_e['LQ製造業'].idxmax() top_mfg_pref = df_e.loc[top_mfg_pref_idx, '都道府県'] example_shares = shares_pct[top_mfg_pref_idx] # 実際の4部門シェア fig4, axes4 = plt.subplots(1, 2, figsize=(13, 5)) fig4.suptitle('修正ウィーバー法(Modified Weaver Method)の解説\n(実データ例示)', fontsize=13, fontweight='bold') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。s[:-n]「末尾n文字を除く」/s[n:]「先頭n文字を除く」。スライス [start:stop:step] はリスト・タプル・文字列共通の基本ワザです。328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | # (a) W_k の変化 ks = range(1, len(SECTORS) + 1) wks = [] sorted_sh_ex = np.sort(example_shares)[::-1] for k in ks: top_k = sorted_sh_ex[:k] w = np.sum((top_k - 100.0 / k) ** 2) wks.append(w) ax4a = axes4[0] ax4a.plot(list(ks), wks, 'o-', color='#1565C0', linewidth=2.5, markersize=9, markerfacecolor='white', markeredgewidth=2.5) opt_k = int(np.argmin(wks)) + 1 ax4a.scatter([opt_k], [wks[opt_k - 1]], color='#E53935', s=130, zorder=5, label=f'最適 k={opt_k}(W_k 最小)') ax4a.set_xlabel('上位k部門数', fontsize=11) ax4a.set_ylabel('W_k(SSD)', fontsize=11) ax4a.set_title(f'W_k の変化({top_mfg_pref} の例)\n部門シェア: {", ".join([f"{v:.0f}" for v in example_shares])}%', fontsize=11, fontweight='bold') ax4a.legend(fontsize=10) ax4a.grid(True, alpha=0.3) for k, w in zip(ks, wks): ax4a.annotate(f'W_{k}={w:.0f}', (k, w), textcoords='offset points', xytext=(8, 5), fontsize=9, color='#E53935' if k == opt_k else '#555') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。np.cumsum(arr) は累積和、np.linspace(a, b, n) は「aからbを等間隔でn個」。NumPyの定石です。353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | # (b) 実際のシェア vs 均等分配(k=opt_k)の比較棒グラフ ax4b = axes4[1] x_pos = np.arange(len(SECTORS)) width = 0.35 # 降順に並べ直して表示 sorted_sector_idx = np.argsort(example_shares)[::-1] sorted_labels = [SECTORS[i] for i in sorted_sector_idx] sorted_shares = example_shares[sorted_sector_idx] ax4b.bar(x_pos - width / 2, sorted_shares, width, label='実際のシェア(実データ)', color='#1565C0', alpha=0.8, edgecolor='white') eq = np.zeros(len(SECTORS)) eq[:opt_k] = 100.0 / opt_k ax4b.bar(x_pos + width / 2, eq, width, label=f'均等分配(k={opt_k})', color='#E65100', alpha=0.7, edgecolor='white') ax4b.set_xticks(x_pos) ax4b.set_xticklabels([f'{s}' for s in sorted_labels], fontsize=9, rotation=15, ha='right') ax4b.set_ylabel('部門シェア(%)', fontsize=11) dominant_sector = SECTORS[np.argmax(example_shares)] ax4b.set_title(f'実際のシェア vs 均等分配(k={opt_k})\n→ {top_mfg_pref}は「{dominant_sector}型」に分類', fontsize=11, fontweight='bold') ax4b.legend(fontsize=9) ax4b.grid(axis='y', alpha=0.3) plt.tight_layout() fig4.savefig(os.path.join(FIG_DIR, '2025_U5_1_fig4_weaver.png'), bbox_inches='tight', dpi=150) plt.close(fig4) print(" → 2025_U5_1_fig4_weaver.png 保存完了") |
図4: ウィーバー法説明図を作成中... → 2025_U5_1_fig4_weaver.png 保存完了
{値:.2f}(小数2桁)、{値:,}(3桁区切り)、{値:>10}(右寄せ10桁)など、覚えると出力が一気に整います。| 学習項目 | 内容 | Pythonでの実装 |
|---|---|---|
| 修正ウィーバー法 | 部門シェアと均等分配のSSDを最小化するk選択 | np.argsort(), np.sum((top_k - equal)**2) |
| 記述統計 | 平均・標準偏差・分位数で分布を把握 | df.describe(), df.groupby().agg() |
| クロス集計 | 2変数のカテゴリ組み合わせを集計 | pd.crosstab(normalize='index') |
| 産業特化係数(LQ) | 地域の産業比重を全国比で評価 | 地域シェア / 全国平均シェア |
| ヒートマップ | クロス集計の視覚的表示 | plt.imshow(), seaborn heatmap() |
| 合成データ生成 | 論文記述に基づくリアルな疑似データ | np.random.default_rng(seed), rng.dirichlet() |
分析スクリプトをダウンロードして実行すると、全図・全集計結果を再現できます。
合成データはスクリプト内で自動生成されます(外部データのダウンロード不要)。
numpy pandas matplotlib scipy sklearnpython3 2025_U5_1_shorei.py(合成データを自動生成して図を保存)
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。