この教材は原論文と同じデータを読み込み、同じ手順で計算し直しています。画面に出る数値と図は、あなたのブラウザがその場で計算した結果です。
| 原論文が使ったデータ | SSDSE-B・海面漁業生産統計調査・海面漁業魚種別漁獲量累年統計(都道府県別)・気象庁 日平均気温の月平均値・気象庁 各都道府県の日平均気温の年の値・気象庁 表面海水中の pH の長期変化傾向 分析単位:都道府県 中核手法:相関分析 |
|---|---|
| この教材が使うデータ |
|
| 原論文(PDF) | 兵庫県の宝「いかなご」を守る 審査員奨励賞/宮川 航、三笠 心菜、百瀨 泉里、山本 祐生、安岡 和希(兵庫県立姫路西高等学校) |
▶ ここに書いてある分析は、ページ下部の「🐍 ブラウザで動かす」でそのまま実行できます(インストール不要)。動かしているのは code/2023_H5_6_shorei.py(395 行)そのものです。
このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
「いかなご(玉筋魚)」は、兵庫県の瀬戸内海沿岸に春の訪れを告げる小魚で、 「いかなごのくぎ煮」として全国的に知られる地域の食文化・経済の象徴的な存在だ。 しかし近年、その漁獲量は急激に減少しており、 2023年には過去最低水準を記録する年もあるなど、深刻な問題となっている。
この論文が挑んだ問いは「地域差を生む社会経済要因は何か」(テーマ:農林水産)。 著者は時系列分析・相関分析・重回帰を軸にこの問いへ定量的に答えを出した。原論文がたどり着いた答えは「高水温と海水pHの低下がいかなご漁獲減少の要因。温暖化抑制と緑化・稚魚放流・漁獲制限を提案」。 本ページではその分析の流れを実データで再現しながら、使われた統計手法を一つずつ学んでいく。
時系列分析 相関分析 散布図 地域比較 環境代理変数
統計センター公表の SSDSE-B(社会・人口統計体系データセット ー 都道府県)を使用。 47都道府県 × 12年度(2012〜2023年)のパネルデータから、 水産業・環境要因に関連する変数を抽出・加工した。
| 変数 | SSDSE-B 列名(実列名) | 役割 |
|---|---|---|
| 年平均気温(°C) | 年平均気温 | 海水温上昇の代理変数。いかなごは低水温域を好む |
| 最高気温(°C) | 最高気温(日最高気温の月平均の最高値) | 極端高温イベントの指標 |
| 年間降水量(mm) | 降水量(年間) | 沿岸への淡水流入・栄養塩供給の代理変数 |
| 高齢化率(%) | 65歳以上人口 / 総人口 × 100 | 漁業コミュニティの担い手不足の指標 |
| 食料費/消費支出(%) | 食料費(二人以上の世帯)/ 消費支出(二人以上の世帯)× 100 | 食への需要構造の変化——いかなご消費の代理 |
| 年度 | 年平均気温 (°C) | 最高気温 (°C) | 降水量 (mm) | 高齢化率 (%) | 食料費割合 (%) |
|---|---|---|---|---|---|
| 2012 | 16.6 | 33.2 | 1,255 | 24.3 | 25.7 |
| 2014 | 16.7 | 30.6 | 1,222 | 26.3 | 26.9 |
| 2016 | 17.8 | 33.7 | 1,347 | 27.8 | 28.4 |
| 2018 | 17.4 | 32.7 | 2,038 | 28.7 | 27.2 |
| 2020 | 17.6 | 34.0 | 1,615 | 28.3 | 29.1 |
| 2022 | 17.5 | 32.3 | 1,161 | 29.8 | 27.4 |
| 2023 | 18.0 | 33.9 | 1,280 | 30.0 | 30.7 |
出典: SSDSE-B-2026(社会・人口統計体系、統計センター)実データ。
SSDSE-B は都道府県×年度の「パネル構造」になっている。 地域コードの正規表現マッチで都道府県行を正確に選択し、 数値変換は文字列列(都道府県名等)を除いて行う必要がある。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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() # 数値変換する列(文字列列は除く) NUM_COLS = [ '総人口', '65歳以上人口', '年平均気温', '最高気温(日最高気温の月平均の最高値)', '降水量(年間)', '消費支出(二人以上の世帯)', '食料費(二人以上の世帯)', '月間有効求人数(一般)', '就職件数(一般)', ] for col in NUM_COLS: if col in df_b.columns: 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ループ不要なのが強み。23 24 25 26 27 28 | # ── 派生変数の計算 ────────────────────────────────────────────── # 高齢化率(%) df_b['高齢化率'] = df_b['65歳以上人口'] / df_b['総人口'] * 100 # 食料費/消費支出 比率(%)— 食への支出割合 df_b['食料費割合'] = df_b['食料費(二人以上の世帯)'] / df_b['消費支出(二人以上の世帯)'] * 100 |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | # 労働市場充足率(求人充足度のプロキシ)— 沿岸漁業町の雇用圧力 df_b['求人充足率'] = df_b['就職件数(一般)'] / df_b['月間有効求人数(一般)'] * 100 # ── 兵庫県データの抽出(2012〜2023)──────────────────────────── hyogo = df_b[df_b['都道府県'] == '兵庫県'].copy() hyogo = hyogo.sort_values('年度').reset_index(drop=True) print("=" * 60) print("■ SSDSE-B 読み込み完了") print(f" 全都道府県×年度行数: {len(df_b)}") print(f" 兵庫県の年度数: {len(hyogo)}年分({hyogo['年度'].min()}〜{hyogo['年度'].max()})") print("=" * 60) print("\n兵庫県 主要変数の時系列サマリー:") print(hyogo[['年度', '年平均気温', '最高気温(日最高気温の月平均の最高値)', '降水量(年間)', '高齢化率', '食料費割合']].to_string(index=False)) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。45 46 47 48 49 50 51 | # ── 沿岸・水産業主要都道府県の定義 ──────────────────────────── COASTAL_PREFS = ['北海道', '青森県', '岩手県', '宮城県', '秋田県', '新潟県', '富山県', '石川県', '福井県', '千葉県', '神奈川県', '静岡県', '愛知県', '三重県', '兵庫県', '和歌山県', '鳥取県', '島根県', '岡山県', '広島県', '山口県', '徳島県', '香川県', '愛媛県', '高知県', '福岡県', '佐賀県', '長崎県', '熊本県', '大分県', '宮崎県', '鹿児島県', '沖縄県'] |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。52 53 54 55 56 57 | # ── 全国平均(都道府県平均)の計算 ─────────────────────────── nat_avg = df_b.groupby('年度')[['食料費割合', '年平均気温']].mean().reset_index() nat_avg = nat_avg.sort_values('年度') # ── 最新年度(2023年)の全都道府県スナップショット ────────────── df_2023 = df_b[df_b['年度'] == 2023].copy().dropna(subset=['年平均気温', '食料費割合']) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。df.groupby('列').apply(関数) — グループごとに関数を適用。時系列や地域別の集計でよく使います。sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。58 59 60 61 62 63 64 | # 沿岸都道府県の2023年スナップ df_coastal_2023 = df_2023[df_2023['都道府県'].isin(COASTAL_PREFS)].copy() df_coastal_2023 = df_coastal_2023.dropna(subset=['降水量(年間)']) df_coastal_2023 = df_coastal_2023.sort_values('降水量(年間)', ascending=False).head(10) print(f"\n■ 2023年 降水量上位10沿岸都道府県:") print(df_coastal_2023[['都道府県', '降水量(年間)', '年平均気温', '食料費割合']].to_string(index=False)) |
============================================================ ■ SSDSE-B 読み込み完了 全都道府県×年度行数: 564 兵庫県の年度数: 12年分(2012〜2023) ============================================================ 兵庫県 主要変数の時系列サマリー: 年度 年平均気温 最高気温(日最高気温の月平均の最高値) 降水量(年間) 高齢化率 食料費割合 2012 16.6 33.2 1254.5 24.304933 25.688369 2013 17.0 33.1 1297.5 25.300988 25.770274 2014 16.7 30.6 1222.0 26.306306 26.865465 2015 17.3 31.7 1578.0 26.769639 27.978756 2016 17.8 33.7 1346.5 27.777778 28.373176 2017 16.8 32.6 1196.0 28.250227 30.294000 2018 17.4 32.7 2037.5 28.667515 27.242090 2019 17.7 32.3 1177.5 28.990525 27.568243 2020 17.6 34.0 1614.5 28.299038 29.109615 2021 17.5 31.3 1637.0 29.602356 27.069571 2022 17.5 32.3 1160.5 29.766753 27.445265 2023 18.0 33.9 1279.5 29.962756 30.713163 ■ 2023年 降水量上位10沿岸都道府県: 都道府県 降水量(年間) 年平均気温 食料費割合 宮崎県 3002.5 18.4 28.389090 高知県 2783.0 17.9 27.160816 鹿児島県 2510.0 19.5 26.526876 福井県 2498.0 16.2 27.404315 富山県 2388.5 16.1 26.501742 静岡県 2382.5 18.2 28.316792 石川県 2333.0 16.6 28.254756 沖縄県 2291.5 23.8 29.238283 秋田県 2208.5 13.7 28.712980 長崎県 2134.5 18.3 29.211075
sort_values('列名', ascending=False) — 指定列で並べ替え(降順)。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。兵庫県の年平均気温・最高気温の推移と、食料費/消費支出比率を重ね合わせた 時系列グラフ。年平均気温は統計的に有意なトレンドで上昇しており(r=0.76, p=0.004)、 2023年には18.0°Cと12年間の最高値を記録した。
スケールの異なる2つの変数(気温と食料費割合)を一枚の図に重ねるには matplotlib の twinx() を使う。軸の色を統一することで可読性を高める。
66 67 68 69 70 71 72 73 74 75 | fig1, ax1a = plt.subplots(figsize=(10, 5)) years = hyogo['年度'].values temp_avg = hyogo['年平均気温'].values temp_max = hyogo['最高気温(日最高気温の月平均の最高値)'].values food_ratio = hyogo['食料費割合'].values color_temp = '#E65100' color_max = '#C62828' color_food = '#1565C0' |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。.map() は「1対1の置き換え」、.apply() は「関数を当てる」。辞書なら .map()、ロジックなら .apply()。76 77 78 79 80 81 | # 左軸: 気温 ax1a.plot(years, temp_avg, 'o-', color=color_temp, linewidth=2.0, markersize=6, label='年平均気温 (°C)') ax1a.plot(years, temp_max, 's--', color=color_max, linewidth=1.5, markersize=5, alpha=0.7, label='最高気温 (°C)') ax1a.fill_between(years, temp_avg, alpha=0.10, color=color_temp) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。ax.fill_between(...) — 2つの曲線で囲まれた領域を塗りつぶし。Lorenz曲線の格差面積などを可視化。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。82 83 84 85 86 87 88 89 90 91 92 | # トレンド線(年平均気温) z1 = stats.linregress(years, temp_avg) ax1a.plot(years, z1.intercept + z1.slope * years, '-', color=color_temp, linewidth=1.0, alpha=0.5, linestyle=':') ax1a.set_xlabel('年度', fontsize=11) ax1a.set_ylabel('気温(°C)', fontsize=11, color=color_temp) ax1a.tick_params(axis='y', labelcolor=color_temp) ax1a.set_xticks(years) ax1a.set_xticklabels([str(y) for y in years], rotation=45, fontsize=9) ax1a.grid(True, alpha=0.25) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。93 94 95 96 97 98 | # 右軸: 食料費割合 ax1b = ax1a.twinx() ax1b.plot(years, food_ratio, 'D-', color=color_food, linewidth=2.0, markersize=5, label='食料費/消費支出 (%)', alpha=0.8) ax1b.set_ylabel('食料費/消費支出 (%)', fontsize=11, color=color_food) ax1b.tick_params(axis='y', labelcolor=color_food) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | # 凡例を統合 lines1, labels1 = ax1a.get_legend_handles_labels() lines2, labels2 = ax1b.get_legend_handles_labels() ax1a.legend(lines1 + lines2, labels1 + labels2, loc='upper left', fontsize=9, framealpha=0.85) r1, p1 = stats.pearsonr(temp_avg, food_ratio) ax1a.set_title( f'兵庫県の気温・食料費の推移(2012〜2023年)\n' f'気温×食料費割合 相関係数 r={r1:.3f}(p={p1:.3f})', fontsize=12, fontweight='bold' ) plt.tight_layout() fig1.savefig(os.path.join(FIG_DIR, '2023_H5_6_fig1_timeseries.png'), bbox_inches='tight', dpi=150) plt.close(fig1) print("\n図1保存: 2023_H5_6_fig1_timeseries.png") |
図1保存: 2023_H5_6_fig1_timeseries.png
stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。2023年の全47都道府県データを用いた散布図。横軸に年平均気温、縦軸に食料費/消費支出比率をとり、 各都道府県の地域特性を視覚化する。兵庫県を赤い星印でハイライトし、 47都道府県の中での位置づけを確認する。
散布図で特定の観測値(例: 兵庫県)を目立たせるには、 scatter() を2回呼ぶか annotate() で矢印ラベルを追加する。 marker='*'(星マーク)と大きめの s(サイズ)が効果的。
117 118 119 120 121 122 123 124 125 | fig2, ax2 = plt.subplots(figsize=(10, 6)) # 全都道府県プロット mask_not_hyogo = df_2023['都道府県'] != '兵庫県' ax2.scatter( df_2023.loc[mask_not_hyogo, '年平均気温'], df_2023.loc[mask_not_hyogo, '食料費割合'], color='#78909C', s=45, alpha=0.65, label='他都道府県', zorder=2 ) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。[式 for x in リスト] はリスト内包表記。forループでappendする代わりに1行でリストを作れます。126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | # 兵庫県ハイライト hyogo_2023 = df_2023[df_2023['都道府県'] == '兵庫県'] ax2.scatter( hyogo_2023['年平均気温'], hyogo_2023['食料費割合'], color='#C62828', s=180, zorder=5, marker='*', label='兵庫県' ) if not hyogo_2023.empty: hx = float(hyogo_2023['年平均気温'].values[0]) hy = float(hyogo_2023['食料費割合'].values[0]) ax2.annotate( '兵庫県', xy=(hx, hy), xytext=(hx + 0.5, hy + 0.3), fontsize=10, color='#C62828', fontweight='bold', arrowprops=dict(arrowstyle='->', color='#C62828', lw=1.2) ) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | # 回帰線 x2 = df_2023['年平均気温'].dropna() y2 = df_2023['食料費割合'].dropna() common2 = df_2023[['年平均気温', '食料費割合']].dropna() x2v = common2['年平均気温'].values y2v = common2['食料費割合'].values z2 = stats.linregress(x2v, y2v) xs2 = [x2v.min(), x2v.max()] ax2.plot(xs2, [z2.intercept + z2.slope * x for x in xs2], 'r-', linewidth=1.5, alpha=0.55, label=f'回帰直線 (r={z2.rvalue:.3f})') r2, p2 = stats.pearsonr(x2v, y2v) ax2.set_xlabel('年平均気温(°C)', fontsize=12) ax2.set_ylabel('食料費/消費支出 (%)', fontsize=12) ax2.set_title( f'年平均気温 vs 食料費割合(2023年, 47都道府県)\n' f'r={r2:.3f}(p={p2:.3f}) 気温が高い地域ほど食料費割合の傾向を確認', fontsize=12, fontweight='bold' ) ax2.legend(fontsize=9, framealpha=0.85) ax2.grid(True, alpha=0.25) plt.tight_layout() fig2.savefig(os.path.join(FIG_DIR, '2023_H5_6_fig2_scatter.png'), bbox_inches='tight', dpi=150) plt.close(fig2) print("図2保存: 2023_H5_6_fig2_scatter.png") |
図2保存: 2023_H5_6_fig2_scatter.png
stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。stats.linregress(x, y) — 単回帰の傾き・切片・r値・p値・標準誤差を返します。使わない値は _ で受け取り。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。兵庫県の食料費/消費支出比率(エンゲル係数に近い指標)の推移を、 47都道府県の平均値と比較する時系列グラフ。 地域特有の食文化(いかなごを含む水産物消費)の変化を需要側から捉える。
170 171 172 173 174 175 176 177 178 179 180 | fig3, ax3 = plt.subplots(figsize=(10, 5)) # 兵庫県 ax3.plot(years, food_ratio, 'o-', color='#C62828', linewidth=2.5, markersize=7, label='兵庫県', zorder=3) # 全国平均 nat_yr = nat_avg['年度'].values nat_fr = nat_avg['食料費割合'].values ax3.plot(nat_yr, nat_fr, 's--', color='#1565C0', linewidth=2.0, markersize=5, alpha=0.8, label='全国平均(47都道府県平均)', zorder=2) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。r, p = stats.pearsonr(...) — Pythonは複数戻り値を同時に受け取れる(タプルアンパック)。181 182 183 184 185 186 187 188 | # 差分の塗りつぶし common_yrs = sorted(set(years) & set(nat_yr)) hy_dict = dict(zip(years, food_ratio)) na_dict = dict(zip(nat_yr, nat_fr)) c_y = [hy_dict[y] for y in common_yrs] c_n = [na_dict[y] for y in common_yrs] ax3.fill_between(common_yrs, c_y, c_n, alpha=0.08, color='#C62828', label='兵庫と全国の差') |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。ax.fill_between(...) — 2つの曲線で囲まれた領域を塗りつぶし。Lorenz曲線の格差面積などを可視化。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | # データラベル(兵庫県) for yr, fr in zip(years, food_ratio): if yr % 2 == 0: ax3.annotate(f'{fr:.1f}%', xy=(yr, fr), xytext=(0, 8), textcoords='offset points', ha='center', fontsize=8, color='#C62828') ax3.set_xlabel('年度', fontsize=11) ax3.set_ylabel('食料費/消費支出 (%)', fontsize=11) ax3.set_xticks(common_yrs) ax3.set_xticklabels([str(y) for y in common_yrs], rotation=45, fontsize=9) ax3.set_title( '食料費/消費支出 比率の推移(2012〜2023年)\n兵庫県 vs 全国平均', fontsize=12, fontweight='bold' ) ax3.legend(fontsize=9, framealpha=0.85) ax3.grid(True, alpha=0.25) plt.tight_layout() fig3.savefig(os.path.join(FIG_DIR, '2023_H5_6_fig3_foodratio.png'), bbox_inches='tight', dpi=150) plt.close(fig3) print("図3保存: 2023_H5_6_fig3_foodratio.png") |
図3保存: 2023_H5_6_fig3_foodratio.png
df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。沿岸部に位置する都道府県の中から、年間降水量の多い上位10道府県を棒グラフで比較する。 降水量は河川を通じた海域への栄養塩(窒素・リン)供給量の指標であり、 瀬戸内海の生態系——特にプランクトン量——に影響する重要な環境変数だ。
棒グラフで特定の都道府県(例: 兵庫県)だけ色を変えるには、 リスト内包表記でcolor リストを作成し、bar() に渡す。
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from scipy import stats import warnings import os warnings.filterwarnings('ignore') plt.rcParams['font.family'] = 'Hiragino Sans' plt.rcParams['axes.unicode_minus'] = False plt.rcParams['figure.dpi'] = 150 FIG_DIR = 'html/figures' DATA_B = '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} のように書式も指定できます。229 230 231 232 233 234 235 236 | fig4, ax4 = plt.subplots(figsize=(11, 6)) pref_names = df_coastal_2023['都道府県'].values rain_vals = df_coastal_2023['降水量(年間)'].values colors4 = ['#C62828' if p == '兵庫県' else '#1565C0' for p in pref_names] bars = ax4.bar(range(len(pref_names)), rain_vals, color=colors4, alpha=0.78, edgecolor='white', width=0.65) |
print はしません。データや図が裏で更新されただけ。次のステップへ進みましょう。fig, ax = plt.subplots(...) — 図全体(fig)と軸(ax)を作る定番。以降は ax.bar(...) 等で操作。x if cond else y は三項演算子。リスト内包表記と組み合わせると、forとifを1行で書けます。237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | # 数値ラベル for i, (bar, val) in enumerate(zip(bars, rain_vals)): ax4.text(bar.get_x() + bar.get_width() / 2, val + 20, f'{val:.0f} mm', ha='center', va='bottom', fontsize=9) ax4.set_xticks(range(len(pref_names))) ax4.set_xticklabels(pref_names, rotation=30, ha='right', fontsize=10) ax4.set_ylabel('年間降水量(mm)', fontsize=11) ax4.set_title( '沿岸主要都道府県の年間降水量(2023年, 上位10道府県)\n' '降水量は沿岸生態系への栄養塩供給・海水塩分濃度に影響', fontsize=12, fontweight='bold' ) ax4.grid(axis='y', alpha=0.25) from matplotlib.patches import Patch ax4.legend(handles=[ Patch(color='#C62828', alpha=0.78, label='兵庫県'), Patch(color='#1565C0', alpha=0.78, label='その他沿岸都道府県'), ], fontsize=9, loc='upper right') plt.tight_layout() fig4.savefig(os.path.join(FIG_DIR, '2023_H5_6_fig4_rainfall.png'), bbox_inches='tight', dpi=150) plt.close(fig4) print("図4保存: 2023_H5_6_fig4_rainfall.png") |
図4保存: 2023_H5_6_fig4_rainfall.png
import pandas as pd など — 必要なライブラリをまとめて呼び出します。as pd は短い別名(alias)。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。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 | print("\n" + "=" * 60) print("■ 兵庫県 環境要因の相関分析サマリー(2012〜2023年, n=12)") print("=" * 60) hyogo_clean = hyogo.dropna(subset=['年平均気温', '降水量(年間)', '高齢化率', '食料費割合']) pairs = [ ('年平均気温', '食料費割合', '気温 × 食料費割合'), ('年度', '年平均気温', '年度 × 年平均気温(温暖化トレンド)'), ('年度', '高齢化率', '年度 × 高齢化率(高齢化進行)'), ('年度', '食料費割合', '年度 × 食料費割合'), ('降水量(年間)', '食料費割合', '降水量 × 食料費割合'), ] print(f"\n {'分析':<35} {'r':>8} {'p値':>10} {'有意':>6}") print(" " + "-" * 63) for x_col, y_col, label in pairs: tmp = hyogo_clean[[x_col, y_col]].dropna() if len(tmp) >= 4: r, p = stats.pearsonr(tmp[x_col].values, tmp[y_col].values) sig = '***' if p < 0.001 else '**' if p < 0.01 else '*' if p < 0.05 else 'n.s.' print(f" {label:<35} {r:>8.4f} {p:>10.4f} {sig:>6}") print("\n全図の生成完了(4枚)") print(" 2023_H5_6_fig1_timeseries.png : 気温・食料費の時系列(兵庫県)") print(" 2023_H5_6_fig2_scatter.png : 気温vs食料費割合 散布図(全47都道府県)") print(" 2023_H5_6_fig3_foodratio.png : 食料費割合 時系列(兵庫 vs 全国)") print(" 2023_H5_6_fig4_rainfall.png : 降水量比較(沿岸上位10道府県)") |
============================================================ ■ 兵庫県 環境要因の相関分析サマリー(2012〜2023年, n=12) ============================================================ 分析 r p値 有意 --------------------------------------------------------------- 気温 × 食料費割合 0.4766 0.1173 n.s. 年度 × 年平均気温(温暖化トレンド) 0.7589 0.0042 ** 年度 × 高齢化率(高齢化進行) 0.9541 0.0000 *** 年度 × 食料費割合 0.5766 0.0497 * 降水量 × 食料費割合 -0.0630 0.8458 n.s. 全図の生成完了(4枚) 2023_H5_6_fig1_timeseries.png : 気温・食料費の時系列(兵庫県) 2023_H5_6_fig2_scatter.png : 気温vs食料費割合 散布図(全47都道府県) 2023_H5_6_fig3_foodratio.png : 食料費割合 時系列(兵庫 vs 全国) 2023_H5_6_fig4_rainfall.png : 降水量比較(沿岸上位10道府県)
stats.pearsonr(x, y) — Pearson相関係数 r と p値を同時に返します。df[col](1列)と df[[col1, col2]](複数列)でカッコの数が違います。リストを渡していると覚えるとミスを減らせます。| 分析の組み合わせ | 相関係数 r | p値 | 解釈 |
|---|---|---|---|
| 年度 × 年平均気温 | 0.759 | 0.004** | 温暖化トレンドが明確に確認できる |
| 年度 × 高齢化率 | 0.954 | 0.000*** | 漁業コミュニティの急速な高齢化が進行 |
| 年度 × 食料費割合 | 0.577 | 0.050* | 食への支出構造が変化しつつある |
| 気温 × 食料費割合 | 0.477 | 0.117 n.s. | 有意とまでは言えないが正の傾向 |
| 降水量 × 食料費割合 | −0.063 | 0.846 n.s. | 直接的な関係は見られない |
** p<0.01, * p<0.05, n.s. = 有意でない。n=12年。
時系列データでは「年度」と強く相関する変数同士(例: 気温と高齢化率)が 偽の相関を持って見える場合がある(spurious correlation)。 n=12という小サンプルでは特に注意が必要。 解釈には「相関はあるが因果ではない」という統計の基本原則を忘れないこと。
| データ・リソース | 出典 |
|---|---|
| SSDSE-B 都道府県データ(2012〜2023年) | 統計センター SSDSE(社会・人口統計体系)、統計センター |
| いかなご漁獲量データ | 農林水産省 漁業・養殖業生産統計、兵庫県水産技術センター |
| 海水温データ | 気象庁 海洋の健康診断表、神戸海洋気象台 |
| 瀬戸内海栄養塩データ | 環境省 公共用水域水質測定結果 |
本教育用コードは SSDSE-B(実公的統計データ)のみを使用。np.random による合成データは一切使用していない。 実際の論文はいかなごの漁獲量実データ・海水温実測値も併用している。
統計分析の解釈で初心者がやりがちな勘違いをまとめます。特に「相関と因果の混同」「p値の過信」は研究現場でもよく起きる落とし穴です。本文を読む前にも、読んだ後にも、目を通してみてください。
統計の基本用語を初心者向けに解説します。本文中で見慣れない言葉が出てきたら、ここに戻って確認してください。
統計手法について「何のためか」「結果をどう読むか」を初心者向けに解説します。
この研究をさらに発展させるための3つの方向性を示します。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに、以下のチャレンジに挑戦してみてください。難易度別に5つ用意しました。
本論文で学んだ手法は、研究の世界だけでなく、行政・企業・NPO の現場でも様々に活用されています。具体的なシーンを紹介します。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。
この論文を理解できたか、クリックで確認しましょう。間違えても解説が出ます。
このページの分析は、この画面の中でそのまま実行できます。
Python をインストールする必要も、CSV をダウンロードする必要もありません。
下のセルの 「▶ ブラウザで実行」 を上から順に押すか、
「▶ 最初から全部実行」 で一気に流してください。
表示されるのは、本文の図表とまったく同じ計算の結果です
(動かしているのは再現スクリプト code/2023_H5_6_shorei.py そのもの)。
コードは書き換えられます。「✏️ 書き換える」で数字や変数を変えて ▶ を押すと、 結果がどう変わるかをその場で確かめられます(元に戻すボタンつき)。 ページを開いた時点で裏で実行環境の準備が始まっているので、待ち時間はほとんどありません。 初回だけ実行環境の取得にインターネット接続が必要です。