この教材は、原論文が使ったデータそのものを使えていません。そこで代わりのデータで同じ問いを追いかけ、結論の向き(増える/減る、強い/弱い)が原論文と一致するかを確かめます。「同じ数値が出る」ことは目標にしていません。
| 原論文が使ったデータ | SSDSE-C・SSDSE-A・国勢調査 分析単位:その他 中核手法:消費重心の算出 |
|---|---|
| この教材が使うデータ | CSV は読み込まない(原論文が報告した数値をそのまま図表化して読み解く) |
| 原論文(PDF) | 家計調査に基づく消費重心の計算 特別賞/井手健太(法政大学経済学部経済学科) |
原論文と同じ粒度のデータは、この教材にも同梱しています。これを読み込めば、原論文と同じ細かさで分析をやり直せます(下の「🐍 ブラウザで動かす」でコードを書き換えて試せます)。ただし原論文が使った項目がすべて収録されているとは限りません。足りない項目は、上の「できないこと」に書いた出典から取ってくる必要があります。
▶ ここに書いてある分析は、ページ下部の「🐍 ブラウザで動かす」でそのまま実行できます(インストール不要)。動かしているのは code/2020_U5_5_shorei.py(302 行)そのものです。
html/figures/ に自動保存されます。
物理学の「重心」は、質量の分布を1点で代表させる考え方である。これを人口に応用したのが人口重心で、総務省統計局は「1人1人が同じ重さを持つと仮定して、調査地域の人口が全体として平衡を保つことができる点」と定義している(総務省統計局 2017)。平成27年国勢調査による我が国の人口重心は東経137度02分15.84秒・北緯35度34分51.44秒(岐阜県付近)で、都市圏への一極集中を反映して東・南方向へ移動を続けている。
本研究の着想は「人口重心の式の“重み”を、人口ではなく家計の消費額に置き換えたらどうなるか」という一点にある。 人口重心が「人がどこに偏って住んでいるか」を1点で表すのに対し、消費額で重み付けした消費重心は「ある品目の消費額がどこに偏っているか」を1点で表す。
人口重心の理論は応用の幅が広い。清水(1958)は昼間・夜間人口の重心を使って都市交通問題を、田村(2019)は人口重心を自然変動と社会変動に要因分解して人口移動を論じている。本研究はこの系譜を家計消費へ拡張する試みである。
消費重心 加重平均 GIS / QGIS 食料品目の地域性
| データ | 内容 | 出所 |
|---|---|---|
| SSDSE-C-2020 | 二人以上世帯・都道府県庁所在市別・食料品目別の年間支出金額(2017〜2019年の平均値) | 統計センター(家計調査) |
| SSDSE-A-2020 | 一般世帯数(列 A710101 ほか) | 統計センター(国勢調査) |
| 人口重心の経度・緯度 | 各都道府県の人口重心(平成27年国勢調査, 表2-3)※SSDSE未収録の外部表 | 総務省統計局(2017) |
人口重心では基本単位区ごとの人口 wi を重みとする。消費重心では、この重みを各県庁所在市の家計消費額 Ci に置き換える。
原論文は北海道・札幌市の「米」を例に説明している。SSDSE-C の札幌市の米の家計消費額 30994 に、SSDSE-A の札幌市の一般世帯数 920415 を掛けて札幌市の米の消費額とする。これを全県庁所在市・全食料品目で行い、各県の人口重心の経度・緯度を掛け合わせて品目ごとに合計し、消費額の合計で割れば消費重心が求まる。
💭 目的:まず、原論文の表1(大分類の消費重心)と小分類213品目の基本統計量を、スクリプト内にそのまま転記する。ここが「報告値の可視化」の土台になる。
このブロックはグラフを描く前の下準備で、必要なライブラリの読み込みと、原論文から書き写した数値の定義だけを行う。
33 34 35 36 37 38 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 66 67 68 69 70 71 72 73 74 75 | import os import math import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.patches import Patch plt.rcParams['font.family'] = 'Hiragino Sans' plt.rcParams['axes.unicode_minus'] = False plt.rcParams['figure.dpi'] = 150 FIG_DIR = 'html/figures' os.makedirs(FIG_DIR, exist_ok=True) NOTE = '報告値の可視化(再計算ではない)' # 全図共通の注記 # ══════════════════════════════════════════════════════════ # 原論文の報告値(PDFのタブル・本文を転記。単位は decimal degrees) # ══════════════════════════════════════════════════════════ # 表1 大分類の消費重心(経度, 緯度) DAIBUNRUI = [ ('穀類', 137.1216, 35.41703), ('魚介類', 137.2183, 35.48567), ('肉類', 136.9404, 35.30843), ('乳卵類', 137.1518, 35.28413), ('野菜・海藻', 137.2787, 35.43841), ('果物', 137.2931, 35.44298), ('油脂・調味料', 137.0571, 35.36921), ('菓子類', 137.1802, 35.42998), ('調理食品', 137.1772, 35.32412), ('飲料', 137.1688, 35.39765), ('酒類', 137.2205, 35.55091), ('外食', 137.3352, 35.35948), ] GOUKEI = ('食料(合計)', 137.1959, 35.39448) # 表1 食料合計 # 図1・図2 小分類213品目の消費重心 経度・緯度の基本統計量(報告値) STATS_LON = dict(平均=137.1901, 標準誤差=0.02256, 中央値=137.1637, 標準偏差=0.32928, 分散=0.10843, 尖度=2.17056, 歪度=-0.22126, 最小=135.7723, 最大=138.2165, n=213) STATS_LAT = dict(平均=35.4238, 標準誤差=0.01231, 中央値=35.4069, 標準偏差=0.17970, 分散=0.03229, 尖度=4.04831, 歪度=0.66821, 最小=34.7792, 最大=36.1986, n=213) |
print しません。ライブラリの読み込みと、原論文 表1(大分類の消費重心)・小分類の基本統計量をスクリプト内の変数に転記しただけです。DAIBUNRUI は表1の12品目の (品目名, 経度, 緯度) をそのまま並べたリスト。GOUKEI は「食料(合計)」の消費重心。STATS_LON/STATS_LAT は小分類213品目の経度・緯度の基本統計量(平均・中央値・標準偏差・歪度・尖度など)で、これらは原論文 図1・図2の報告値です。dict(平均=137.19, ...) は「名前つきの値」をまとめる型。STATS_LON["平均"] のように名前で取り出せます。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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | # 表2 経度に特徴のある消費品目(西側=経度が小さい / 東側=経度が大きい) WEST = [ # 西に位置する10品目(経度が小さい順) ('たい', 135.7723, 34.7792), ('まんじゅう', 136.2335, 35.05084), ('あじ', 136.2797, 34.8392), ('合いびき肉', 136.3631, 34.9684), ('揚げかまぼこ', 136.4847, 35.0584), ('ぶり', 136.4962, 35.0493), ('さば', 136.5260, 35.1315), ('そうざい材料セット', 136.5547, 35.1627), ('牛肉', 136.5805, 35.0234), ('いわし', 136.5829, 35.1546), ] EAST = [ # 東に位置する10品目(経度が大きい順) ('まぐろ', 138.2165, 35.5758), ('グレープフルーツ', 138.0606, 35.7085), ('しじみ', 138.0287, 35.9265), ('魚介の漬物', 138.0014, 35.9617), ('しゅうまい', 137.9851, 35.4739), ('ワイン', 137.9358, 35.5691), ('ウイスキー', 137.8987, 35.9656), ('塩さけ', 137.8681, 35.9674), ('ほたて貝', 137.8290, 36.1005), ('さやまめ', 137.7646, 35.4946), ] # 表3 緯度に特徴のある消費品目(南側=緯度が小さい / 北側=緯度が大きい) SOUTH = [ ('たい', 135.7723, 34.7792), ('あじ', 136.2797, 34.8392), ('合いびき肉', 136.3631, 34.9684), ('牛肉', 136.5805, 35.0234), ('ぶり', 136.4962, 35.0493), ('揚げかまぼこ', 136.4847, 35.0584), ('まんじゅう', 136.2335, 35.05084), ('かつお節・削り節', 136.8234, 35.0757), ('さば', 136.5260, 35.1315), ('いわし', 136.5829, 35.1546), ] NORTH = [ ('メロン', 137.681509, 36.1986493), ('ほたて貝', 137.828986, 36.1005324), ('塩さけ', 137.868137, 35.9674378), ('ウイスキー', 137.898738, 35.9655654), ('魚介の漬物', 138.001437, 35.9616854), ('かれい', 137.168282, 35.9436351), ('しじみ', 138.028741, 35.9265045), ('他の貝', 137.528317, 35.8431935), ('さんま', 137.562414, 35.7237647), ('グレープフルーツ', 138.06064, 35.7084886), ] # 本文で言及される代表品目(対照分析用, 報告値) CONTRAST = { '牛肉': (136.5805, 35.02335), '豚肉': (137.1804, 35.43735), 'たい': (135.7723, 34.7792), 'まぐろ': (138.2165, 35.5758), } # 人口重心(総務省統計局2017, 平成27年国勢調査, 全国) # 原論文本文の報告値: 東経137度02分15.84秒, 北緯35度34分51.44秒 JINKO_JUSHIN_DMS = '東経137度02分15.84秒 / 北緯35度34分51.44秒' JINKO_JUSHIN = (137 + 2/60 + 15.84/3600, 35 + 34/60 + 51.44/3600) # ≈(137.0377, 35.5810) REPORTED_KM_JINKO = 16.75 # 人口重心と食料全体の消費重心の距離(報告値) REPORTED_KM_BUTA_GYU = 71.411 # 豚肉と牛肉の消費重心間距離(報告値) def haversine_km(a, b): """2地点 (lon, lat) 間の大円距離[km]。報告座標の整合性確認に使用。""" R = 6371.0 lon1, lat1 = math.radians(a[0]), math.radians(a[1]) lon2, lat2 = math.radians(b[0]), math.radians(b[1]) dlon, dlat = lon2 - lon1, lat2 - lat1 h = math.sin(dlat/2)**2 + math.cos(lat1)*math.cos(lat2)*math.sin(dlon/2)**2 return 2 * R * math.asin(math.sqrt(h)) |
print しません。表2(経度に特徴のある品目)・表3(緯度に特徴のある品目)・対照品目・人口重心の値を転記し、2点間の距離を測る haversine_km 関数を定義しています。WEST/EAST は表2(西10・東10品目)、SOUTH/NORTH は表3(南10・北10品目)の報告値です。haversine_km は地球を球とみなして経度・緯度から2地点の距離を求める関数。これは報告値どうしの整合性チェック(例:牛肉と豚肉の距離が報告値71.411kmに一致するか)に使います。137 + 2/60 + 15.84/3600 のように書けます。🔗 転記した数値が原論文と食い違っていないかを、コンソール出力と距離計算で確認する。
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | # ══════════════════════════════════════════════════════════ # コンソール出力:報告値の確認 # ══════════════════════════════════════════════════════════ print('=' * 64) print('家計調査に基づく消費重心の計算 — 原論文の報告値(可視化用)') print('=' * 64) print(f'食料全体の消費重心(表1 食料合計): 経度 {GOUKEI[1]}, 緯度 {GOUKEI[2]}') print(f'人口重心(平成27年国勢調査) : {JINKO_JUSHIN_DMS}') print(f' → 消費重心は人口重心より東北東へ約 {REPORTED_KM_JINKO} km(原論文の報告値)') print('\n── 大分類で最も西/東に位置した消費重心(表1)──') lon_sorted = sorted(DAIBUNRUI, key=lambda t: t[1]) print(f' 最も西: {lon_sorted[0][0]}(経度 {lon_sorted[0][1]})') print(f' 最も東: {lon_sorted[-1][0]}(経度 {lon_sorted[-1][1]})') print('\n── 小分類213品目の経度・緯度の基本統計量(図1・図2, 報告値)──') print(f' 経度: 平均{STATS_LON["平均"]} 中央値{STATS_LON["中央値"]} ' f'標準偏差{STATS_LON["標準偏差"]} 歪度{STATS_LON["歪度"]} 尖度{STATS_LON["尖度"]}') print(f' 緯度: 平均{STATS_LAT["平均"]} 中央値{STATS_LAT["中央値"]} ' f'標準偏差{STATS_LAT["標準偏差"]} 歪度{STATS_LAT["歪度"]} 尖度{STATS_LAT["尖度"]}') print('\n── 報告座標による品目間距離の整合性チェック(haversine)──') d_bg = haversine_km(CONTRAST['牛肉'], CONTRAST['豚肉']) d_tm = haversine_km(CONTRAST['たい'], CONTRAST['まぐろ']) print(f' 牛肉↔豚肉: 計算 {d_bg:.3f} km(原論文の報告値 {REPORTED_KM_BUTA_GYU} km)') print(f' たい↔まぐろ: 計算 {d_tm:.3f} km(東西の代替的関係)') |
================================================================ 家計調査に基づく消費重心の計算 — 原論文の報告値(可視化用) ================================================================ 食料全体の消費重心(表1 食料合計): 経度 137.1959, 緯度 35.39448 人口重心(平成27年国勢調査) : 東経137度02分15.84秒 / 北緯35度34分51.44秒 → 消費重心は人口重心より東北東へ約 16.75 km(原論文の報告値) ── 大分類で最も西/東に位置した消費重心(表1)── 最も西: 肉類(経度 136.9404) 最も東: 外食(経度 137.3352) ── 小分類213品目の経度・緯度の基本統計量(図1・図2, 報告値)── 経度: 平均137.1901 中央値137.1637 標準偏差0.32928 歪度-0.22126 尖度2.17056 緯度: 平均35.4238 中央値35.4069 標準偏差0.1797 歪度0.66821 尖度4.04831 ── 報告座標による品目間距離の整合性チェック(haversine)── 牛肉↔豚肉: 計算 71.331 km(原論文の報告値 71.411 km) たい↔まぐろ: 計算 239.146 km(東西の代替的関係)
f"…{x:.3f}…" は小数点以下3桁で埋め込む書式。桁を揃えると数値の比較が読みやすくなります。家計調査の食料12大分類について、原論文が報告した消費重心(経度・緯度)は次のとおり。青は最も西の肉類、緑は最も東の外食。
| 大分類 | 経度(東経) | 緯度(北緯) |
|---|---|---|
| 01 穀類 | 137.1216 | 35.41703 |
| 02 魚介類 | 137.2183 | 35.48567 |
| 03 肉類 | 136.9404 | 35.30843 |
| 04 乳卵類 | 137.1518 | 35.28413 |
| 05 野菜・海藻 | 137.2787 | 35.43841 |
| 06 果物 | 137.2931 | 35.44298 |
| 07 油脂・調味料 | 137.0571 | 35.36921 |
| 08 菓子類 | 137.1802 | 35.42998 |
| 09 調理食品 | 137.1772 | 35.32412 |
| 10 飲料 | 137.1688 | 35.39765 |
| 11 酒類 | 137.2205 | 35.55091 |
| 12 外食 | 137.3352 | 35.35948 |
| 食料(合計) | 137.1959 | 35.39448 |
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | # ══════════════════════════════════════════════════════════ # 図1: 大分類12品目の消費重心の分布(経度×緯度, 表1の報告値) # ══════════════════════════════════════════════════════════ fig1, ax1 = plt.subplots(figsize=(10, 7)) lons = [t[1] for t in DAIBUNRUI] lats = [t[2] for t in DAIBUNRUI] ax1.scatter(lons, lats, s=90, color='#f0a500', edgecolors='#7c5a00', linewidths=0.8, zorder=3, label='大分類の消費重心(12品目)') for name, lon, lat in DAIBUNRUI: ax1.annotate(name, (lon, lat), fontsize=9, ha='left', va='bottom', xytext=(3, 3), textcoords='offset points') # 食料合計 ax1.scatter([GOUKEI[1]], [GOUKEI[2]], s=180, marker='*', color='#c62828', edgecolors='black', linewidths=0.8, zorder=4, label='食料(合計)の消費重心') ax1.annotate('食料(合計)', (GOUKEI[1], GOUKEI[2]), fontsize=10, fontweight='bold', color='#c62828', ha='right', va='top', xytext=(-4, -4), textcoords='offset points') # 最西・最東の強調(重ね塗り) ax1.scatter([lon_sorted[0][1]], [lon_sorted[0][2]], s=90, color='#1565C0', edgecolors='black', linewidths=0.8, zorder=5) ax1.scatter([lon_sorted[-1][1]], [lon_sorted[-1][2]], s=90, color='#2E7D32', edgecolors='black', linewidths=0.8, zorder=5) ax1.text(0.02, 0.97, '青=最も西(肉類) 緑=最も東(外食)', transform=ax1.transAxes, fontsize=10, va='top', ha='left', bbox=dict(boxstyle='round,pad=0.3', fc='#FFF8E1', ec='#F9A825', alpha=0.9)) ax1.set_xlabel('経度(東経・度)→ 東', fontsize=12) ax1.set_ylabel('緯度(北緯・度)→ 北', fontsize=12) ax1.set_title(f'図1 大分類の消費重心の分布(経度×緯度)\n原論文 表1・{NOTE}', fontsize=13, fontweight='bold') ax1.legend(loc='lower right', fontsize=10, framealpha=0.9) ax1.grid(True, alpha=0.3, linestyle='--') ax1.spines[['top', 'right']].set_visible(False) fig1.tight_layout() fig1.savefig(os.path.join(FIG_DIR, '2020_U5_5_fig1.png'), dpi=150, bbox_inches='tight') plt.close(fig1) print('\n図1 保存完了: 2020_U5_5_fig1.png') |
図1 保存完了: 2020_U5_5_fig1.png
ax1.annotate で各点に品目名を添えています。図タイトルに「報告値の可視化(再計算ではない)」と明記しています。ax.scatter(x, y) は点を打つ関数。marker="*" で星印など形を変えられます。
大分類をさらに細かくした小分類213品目の消費重心について、原論文が示した経度・緯度の基本統計量は次のとおり。
| 統計量 | 経度(東経) | 緯度(北緯) |
|---|---|---|
| 平均 | 137.1901 | 35.4238 |
| 中央値 | 137.1637 | 35.4069 |
| 標準偏差 | 0.32928 | 0.17970 |
| 歪度 | -0.22126 | 0.66821 |
| 尖度 | 2.17056 | 4.04831 |
| 最小 / 最大 | 135.7723 / 138.2165 | 34.7792 / 36.1986 |
| データ数 | 213 | 213 |
消費重心の経度が最も小さい(西)・最も大きい(東)品目、各10品目を原論文がまとめている。
| 西に位置する10品目 | 東に位置する10品目 | ||||
|---|---|---|---|---|---|
| 品目 | 経度 | 緯度 | 品目 | 経度 | 緯度 |
| たい | 135.7723 | 34.7792 | まぐろ | 138.2165 | 35.5758 |
| まんじゅう | 136.2335 | 35.05084 | グレープフルーツ | 138.0606 | 35.7085 |
| あじ | 136.2797 | 34.8392 | しじみ | 138.0287 | 35.9265 |
| 合いびき肉 | 136.3631 | 34.9684 | 魚介の漬物 | 138.0014 | 35.9617 |
| 揚げかまぼこ | 136.4847 | 35.0584 | しゅうまい | 137.9851 | 35.4739 |
| ぶり | 136.4962 | 35.0493 | ワイン | 137.9358 | 35.5691 |
| さば | 136.526 | 35.1315 | ウイスキー | 137.8987 | 35.9656 |
| そうざい材料セット | 136.5547 | 35.1627 | 塩さけ | 137.8681 | 35.9674 |
| 牛肉 | 136.5805 | 35.0234 | ほたて貝 | 137.829 | 36.1005 |
| いわし | 136.5829 | 35.1546 | さやまめ | 137.7646 | 35.4946 |
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | # ══════════════════════════════════════════════════════════ # 図2: 経度に特徴のある消費品目(西10・東10, 表2の報告値) # ══════════════════════════════════════════════════════════ items = list(reversed(WEST)) + list(reversed(EAST)) # 下=西, 上=東 になるよう配置 names = [t[0] for t in items] vals = [t[1] for t in items] colors = ['#1565C0'] * len(WEST) + ['#2E7D32'] * len(EAST) fig2, ax2 = plt.subplots(figsize=(10, 9)) ax2.barh(range(len(items)), vals, color=colors, alpha=0.85, edgecolor='white', linewidth=0.5) ax2.axvline(GOUKEI[1], color='#c62828', linewidth=1.5, linestyle='--', label=f'食料(合計)の経度 {GOUKEI[1]}') ax2.set_yticks(range(len(items))) ax2.set_yticklabels(names, fontsize=10) for i, v in enumerate(vals): ax2.text(v + 0.006, i, f'{v:.4f}', va='center', fontsize=8, color='#333') ax2.set_xlabel('経度(東経・度) ←西 東→', fontsize=12) ax2.set_title(f'図2 経度に特徴のある消費品目(西10・東10)\n原論文 表2・{NOTE}', fontsize=13, fontweight='bold') ax2.set_xlim(135.5, 138.5) handles = [Patch(facecolor='#1565C0', alpha=0.85, label='西に位置(暖流・西日本の漁業等)'), Patch(facecolor='#2E7D32', alpha=0.85, label='東に位置(寒流・東日本の産地等)'), plt.Line2D([0], [0], color='#c62828', linestyle='--', label=f'食料(合計){GOUKEI[1]}')] ax2.legend(handles=handles, loc='lower right', fontsize=9, framealpha=0.9) ax2.grid(True, axis='x', alpha=0.3, linestyle='--') ax2.spines[['top', 'right']].set_visible(False) fig2.tight_layout() fig2.savefig(os.path.join(FIG_DIR, '2020_U5_5_fig2.png'), dpi=150, bbox_inches='tight') plt.close(fig2) print('図2 保存完了: 2020_U5_5_fig2.png') |
図2 保存完了: 2020_U5_5_fig2.png
ax.barh は横棒、ax.axvline は縦の基準線。並び順は下=西・上=東になるよう反転させています。list(reversed(x)) でリストの並びを逆にできます。横棒は下から積まれるので、表示順を整えるときに使います。
同様に、消費重心の緯度が最も小さい(南)・最も大きい(北)品目、各10品目を原論文がまとめている。
| 南に位置する10品目 | 北に位置する10品目 | ||||
|---|---|---|---|---|---|
| 品目 | 経度 | 緯度 | 品目 | 経度 | 緯度 |
| たい | 135.7723 | 34.7792 | メロン | 137.681509 | 36.1986493 |
| あじ | 136.2797 | 34.8392 | ほたて貝 | 137.828986 | 36.1005324 |
| 合いびき肉 | 136.3631 | 34.9684 | 塩さけ | 137.868137 | 35.9674378 |
| 牛肉 | 136.5805 | 35.0234 | ウイスキー | 137.898738 | 35.9655654 |
| ぶり | 136.4962 | 35.0493 | 魚介の漬物 | 138.001437 | 35.9616854 |
| 揚げかまぼこ | 136.4847 | 35.0584 | かれい | 137.168282 | 35.9436351 |
| まんじゅう | 136.2335 | 35.05084 | しじみ | 138.028741 | 35.9265045 |
| かつお節・削り節 | 136.8234 | 35.0757 | 他の貝 | 137.528317 | 35.8431935 |
| さば | 136.526 | 35.1315 | さんま | 137.562414 | 35.7237647 |
| いわし | 136.5829 | 35.1546 | グレープフルーツ | 138.06064 | 35.7084886 |
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 | # ══════════════════════════════════════════════════════════ # 図3: 緯度に特徴のある消費品目(南10・北10, 表3の報告値) # ══════════════════════════════════════════════════════════ items3 = list(reversed(SOUTH)) + list(reversed(NORTH)) # 下=南, 上=北 names3 = [t[0] for t in items3] vals3 = [t[2] for t in items3] colors3 = ['#E65100'] * len(SOUTH) + ['#00695C'] * len(NORTH) fig3, ax3 = plt.subplots(figsize=(10, 9)) ax3.barh(range(len(items3)), vals3, color=colors3, alpha=0.85, edgecolor='white', linewidth=0.5) ax3.axvline(GOUKEI[2], color='#c62828', linewidth=1.5, linestyle='--', label=f'食料(合計)の緯度 {GOUKEI[2]}') ax3.set_yticks(range(len(items3))) ax3.set_yticklabels(names3, fontsize=10) for i, v in enumerate(vals3): ax3.text(v + 0.004, i, f'{v:.4f}', va='center', fontsize=8, color='#333') ax3.set_xlabel('緯度(北緯・度) ←南 北→', fontsize=12) ax3.set_title(f'図3 緯度に特徴のある消費品目(南10・北10)\n原論文 表3・{NOTE}', fontsize=13, fontweight='bold') ax3.set_xlim(34.5, 36.4) handles3 = [Patch(facecolor='#E65100', alpha=0.85, label='南に位置(九州・四国の影響)'), Patch(facecolor='#00695C', alpha=0.85, label='北に位置(北海道の名産品)'), plt.Line2D([0], [0], color='#c62828', linestyle='--', label=f'食料(合計){GOUKEI[2]}')] ax3.legend(handles=handles3, loc='lower right', fontsize=9, framealpha=0.9) ax3.grid(True, axis='x', alpha=0.3, linestyle='--') ax3.spines[['top', 'right']].set_visible(False) fig3.tight_layout() fig3.savefig(os.path.join(FIG_DIR, '2020_U5_5_fig3.png'), dpi=150, bbox_inches='tight') plt.close(fig3) print('図3 保存完了: 2020_U5_5_fig3.png') |
図3 保存完了: 2020_U5_5_fig3.png
経度・緯度を組み合わせると、品目間の位置関係や「距離」も測れる。原論文は牛肉と豚肉の消費重心間距離を 71.411km(CASIO 高性能計算サイトで算出)と報告している。たいとまぐろは東西に大きく離れ、代替的な関係がうかがえる。
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 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | # ══════════════════════════════════════════════════════════ # 図4: 品目間の対照(牛肉↔豚肉, たい↔まぐろ)と距離(報告値) # ══════════════════════════════════════════════════════════ fig4, ax4 = plt.subplots(figsize=(10, 7)) pair_style = { '牛肉': ('#C62828', 'o'), '豚肉': ('#C62828', 's'), 'たい': ('#1565C0', 'o'), 'まぐろ': ('#1565C0', 's'), } for name, (lon, lat) in CONTRAST.items(): col, mk = pair_style[name] ax4.scatter([lon], [lat], s=140, color=col, marker=mk, edgecolors='black', linewidths=0.7, zorder=3) ax4.annotate(name, (lon, lat), fontsize=11, fontweight='bold', color=col, ha='left', va='bottom', xytext=(4, 4), textcoords='offset points') # 対照ペアを線で結ぶ for pair, kmtext in [(('牛肉', '豚肉'), f'牛肉と豚肉 {REPORTED_KM_BUTA_GYU} km'), (('たい', 'まぐろ'), 'たいとまぐろ(東西の代替)')]: a, b = CONTRAST[pair[0]], CONTRAST[pair[1]] ax4.plot([a[0], b[0]], [a[1], b[1]], color='#888', linestyle='--', linewidth=1.2, zorder=2) mx, my = (a[0]+b[0])/2, (a[1]+b[1])/2 ax4.annotate(kmtext, (mx, my), fontsize=9, color='#555', ha='center', va='center', bbox=dict(boxstyle='round,pad=0.2', fc='white', ec='#bbb', alpha=0.9)) # 食料合計 ax4.scatter([GOUKEI[1]], [GOUKEI[2]], s=200, marker='*', color='#f0a500', edgecolors='black', linewidths=0.8, zorder=4, label='食料(合計)') ax4.annotate('食料(合計)', (GOUKEI[1], GOUKEI[2]), fontsize=10, ha='right', va='top', xytext=(-4, -4), textcoords='offset points') ax4.set_xlabel('経度(東経・度)→ 東', fontsize=12) ax4.set_ylabel('緯度(北緯・度)→ 北', fontsize=12) ax4.set_title(f'図4 品目間の対照:牛肉と豚肉・たいとまぐろの消費重心\n原論文本文・{NOTE}', fontsize=13, fontweight='bold') ax4.legend(loc='lower right', fontsize=10, framealpha=0.9) ax4.grid(True, alpha=0.3, linestyle='--') ax4.spines[['top', 'right']].set_visible(False) fig4.tight_layout() fig4.savefig(os.path.join(FIG_DIR, '2020_U5_5_fig4.png'), dpi=150, bbox_inches='tight') plt.close(fig4) print('図4 保存完了: 2020_U5_5_fig4.png') print('\n全図生成完了。') |
図4 保存完了: 2020_U5_5_fig4.png 全図生成完了。
html/figures/ に保存されます。ax.plot([x1,x2],[y1,y2]) は2点を線で結びます。linestyle="--" で破線になります。
これらの誤差を小さくする工夫を前提に、消費重心は食品以外の品目や、複数年での重心の移動距離(経年変化)の分析にも応用できる可能性がある。近年の消費傾向や人口との関連を見出す1つの尺度になりうる。
消費重心は直感的に見えて、読み違えやすいポイントがいくつもあります。
本ページに出てくる主な用語をまとめます。
本論文で使われた「重心(加重平均)」まわりの手法を、注意点つきで整理します。データはすべて統計センター提供の教育用標準データセット(SSDSE)を用いています。
この研究をさらに発展させる3つの方向性です。
スクリプトをベースに手を動かしてみましょう。
haversine_km を使って、たとえば「ぶりとまぐろ」など別ペアの重心距離を計算してください。「重み付きの重心」で地域性を1点に要約する発想は、現場で広く使われています。
初心者が抱きやすい疑問に答えます。
この論文を理解できたか、クリックで確認しましょう。間違えても解説が出ます。
このページの分析は、この画面の中でそのまま実行できます。
Python をインストールする必要も、CSV をダウンロードする必要もありません。
下のセルの 「▶ ブラウザで実行」 を上から順に押すか、
「▶ 最初から全部実行」 で一気に流してください。
表示されるのは、本文の図表とまったく同じ計算の結果です
(動かしているのは再現スクリプト code/2020_U5_5_shorei.py そのもの)。
コードは書き換えられます。「✏️ 書き換える」で数字や変数を変えて ▶ を押すと、 結果がどう変わるかをその場で確かめられます(元に戻すボタンつき)。 ページを開いた時点で裏で実行環境の準備が始まっているので、待ち時間はほとんどありません。 初回だけ実行環境の取得にインターネット接続が必要です。