この教材は原論文と同じデータを読み込み、同じ手順で計算し直しています。画面に出る数値と図は、あなたのブラウザがその場で計算した結果です。
| 原論文が使ったデータ | 住民基本台帳に基づく人口、人口動態及び世帯数・人口推計・SSDSE-B-2021・在留外国人統計・過去の気象データ・統計でみる都道府県のすがた 2021・平成 29 年度日本語教育実態調査・労働力調査(基本集計)・工業統計調査・SSDSE-2020A 分析単位:都道府県 中核手法:相関分析 |
|---|---|
| この教材が使うデータ |
|
| 原論文(PDF) | 外国人にとっての暮らしやすさとは 統計活用奨励賞/谷 優輝(慶應義塾湘南藤沢高等部) |
▶ ここに書いてある分析は、ページ下部の「🐍 ブラウザで動かす」でそのまま実行できます(インストール不要)。動かしているのは code/2021_H4_katsuyo.py(178 行)そのものです。
このページの分析を自分で再現するには、以下の手順でデータを準備してください。コードの編集は不要です。
data/raw/ フォルダに入れます。html/figures/ に自動保存されます。
日本の総人口は2011年以降、年々減少している。国立社会保障・人口問題研究所の「日本の将来推計人口(平成29年推計)」では、2017年時点の総人口の約30%分が2065年までにいなくなると予測された。一方で、日本に住む外国人の人口は年々増加しており(総務省の集計では増加数・総人口に占める割合ともに過去最高を更新)、その年齢構成は20〜39歳が約半分を占め、日本全体より若い。
そこで原論文の著者は「外国人に移り住んでもらうことが、人口減少・少子化を和らげる足掛かりになるのではないか」と考えた。 そのためには「外国人にとって暮らしやすい=移住したくなる地域の条件は何か」を明らかにする必要がある。 本研究は都道府県別の外国人人口割合を「暮らしやすさの結果」ととらえ、それを高める要因を統計的に探る。
SSDSE-B ピアソンの積率相関係数 散布図・回帰直線 要因の仮説検証
本教材は独立行政法人統計センターの SSDSE(教育用標準データセット)-B 2026年版の2019年断面(47都道府県)を用いる。原論文は下表の多様な出典を組み合わせているが、本教材で実際に再計算できるのは SSDSE-B に収録された「総人口・日本人人口・年平均気温」に基づく部分のみである。
| 変数 | 出典(原論文) | 本教材での扱い |
|---|---|---|
| 都道府県別 総人口・日本人人口 | 人口推計(総務省統計局)2019年 | SSDSE-Bで実再現 |
| 都道府県別 外国人人口 | 在留外国人統計(法務省出入国在留管理庁)2019年 | 総人口−日本人人口で代用 |
| 年平均気温 | 気象庁「過去の気象データ」2019年(SSDSE-B収録) | SSDSE-Bで実再現 |
| 年平均相対湿度 | 統計でみる都道府県のすがた2021(総務省統計局) | 報告値を引用 |
| 日本語教育実施機関・施設等数(一般) | 平成29年度日本語教育実態調査(文化庁) | 報告値を引用 |
| 日本語の常勤教師数 | 平成29年度日本語教育実態調査(文化庁) | 報告値を引用 |
| 完全失業率 | 労働力調査 基本集計(総務省統計局)2019年 | 報告値を引用 |
| 製造物出荷額 | 工業統計調査(経済産業省)2019年 | 報告値を引用 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import os import numpy as np import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from scipy import stats 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) df_b = pd.read_csv(DATA_B, encoding='cp932', header=1) df_b = df_b[df_b['地域コード'].str.match(r'^R\d{5}', na=False)].copy() df_b['年度'] = df_b['年度'].astype(int) # 原論文に合わせ 2019 年断面を使用 df = df_b[df_b['年度'] == 2019].copy().reset_index(drop=True) assert len(df) == 47, f"47都道府県のはずが {len(df)} 行" # 外国人人口 = 総人口 - 日本人人口(原論文 表2 の定義) df['外国人人口'] = df['総人口'] - df['日本人人口'] df['外国人人口割合'] = df['外国人人口'] / df['総人口'] * 100 print(f"対象: {df['年度'].iloc[0]}年 {len(df)}都道府県") print(f"外国人人口割合 平均 {df['外国人人口割合'].mean():.3f}% 中央値 {df['外国人人口割合'].median():.3f}%") |
対象: 2019年 47都道府県 外国人人口割合 平均 1.516% 中央値 1.357%
header=1 でSSDSE-Bの2行目(日本語列名)を見出しにし、地域コードが「R+数字5桁」の47都道府県行だけを残します。外国人人口 = 総人口 − 日本人人口。これは原論文 表2 の全国値の作り方を都道府県単位に適用したもの。原論文本体は都道府県の外国人人口に法務省「在留外国人統計」を使っていますが、SSDSEだけで完結させるため差分方式で再現しています。df['A'] - df['B'] のような列同士の演算は要素ごと(行ごと)に実行され、forループは不要です。32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | region_map = { '北海道': '北海道・東北', '青森県': '北海道・東北', '岩手県': '北海道・東北', '宮城県': '北海道・東北', '秋田県': '北海道・東北', '山形県': '北海道・東北', '福島県': '北海道・東北', '茨城県': '関東', '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東', '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部', '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部', '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿', '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿', '鳥取県': '中国・四国', '島根県': '中国・四国', '岡山県': '中国・四国', '広島県': '中国・四国', '山口県': '中国・四国', '徳島県': '中国・四国', '香川県': '中国・四国', '愛媛県': '中国・四国', '高知県': '中国・四国', '福岡県': '九州・沖縄', '佐賀県': '九州・沖縄', '長崎県': '九州・沖縄', '熊本県': '九州・沖縄', '大分県': '九州・沖縄', '宮崎県': '九州・沖縄', '鹿児島県': '九州・沖縄', '沖縄県': '九州・沖縄' } region_colors = { '北海道・東北': '#4e9af1', '関東': '#e05c5c', '中部': '#f0a500', '近畿': '#5cb85c', '中国・四国': '#9b59b6', '九州・沖縄': '#f39c12' } df['地域'] = df['都道府県'].map(region_map) df['色'] = df['地域'].map(region_colors) print(df['地域'].value_counts().to_string()) |
地域 中部 9 中国・四国 9 九州・沖縄 8 北海道・東北 7 関東 7 近畿 7
Series.map(辞書) は「1対1の置き換え」。都道府県名から地域名・色コードへ一気に変換しています。.map()、条件分岐のロジックを当てるなら .apply() と使い分けます。まず47都道府県の外国人人口割合を高い順に並べ、全体像をつかむ。原論文4.1では市区町村別の箱ひげ図(図4)から「大半の市区町村は1%以下で、長野県川上村15.76%・群馬県大泉町14.46%などが突出」と報告している。本教材は市区町村データを持たないため、都道府県レベルのランキングで再現する。
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | ds = df.sort_values('外国人人口割合', ascending=False).reset_index(drop=True) short = [s.replace('県','').replace('府','').replace('都','').replace('道','') for s in ds['都道府県']] fig1, ax1 = plt.subplots(figsize=(12, 6)) ax1.bar(range(len(ds)), ds['外国人人口割合'], color=ds['色'], edgecolor='white', linewidth=0.5) ax1.set_xticks(range(len(ds))) ax1.set_xticklabels(short, rotation=90, fontsize=8) ax1.set_ylabel('外国人人口割合 [%]', fontsize=12) ax1.set_title('図1:都道府県別 外国人人口割合ランキング(2019年・SSDSE-Bより再現)', fontsize=13) ax1.axhline(ds['外国人人口割合'].mean(), color='gray', ls='--', lw=1, label=f"全国平均 {ds['外国人人口割合'].mean():.2f}%") from matplotlib.patches import Patch handles = [Patch(facecolor=c, label=r) for r, c in region_colors.items()] handles.append(ax1.get_legend_handles_labels()[0][0]) ax1.legend(handles=handles, fontsize=9, ncol=2) ax1.grid(True, axis='y', alpha=0.3) fig1.tight_layout() fig1.savefig(os.path.join(FIG_DIR, '2021_H4_fig1.png'), bbox_inches='tight') plt.close(fig1) print("上位5:"); print(ds.head(5)[['都道府県','外国人人口割合']].to_string(index=False)) print("下位5:"); print(ds.tail(5)[['都道府県','外国人人口割合']].to_string(index=False)) |
上位5: 都道府県 外国人人口割合 東京都 4.033697 愛知県 3.387588 群馬県 2.924577 三重県 2.748177 大阪府 2.601221 下位5: 都道府県 外国人人口割合 和歌山県 0.644468 高知県 0.572246 宮崎県 0.557103 青森県 0.478851 秋田県 0.411523
ax.axhline(値) は水平の基準線。平均値やしきい値を1本引くだけで、各県が平均より上か下かが一目で分かります。原論文4.2/図5の中心的発見は「都道府県の人口が多いほど外国人人口割合も高い」という正の相関である。原論文は在留外国人統計を用いて相関係数 0.661 を報告した。ここでは SSDSE-B から独立に再現する。
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 | x = df['総人口'] / 10000 # 万人 y = df['外国人人口割合'] r, p = stats.pearsonr(x, y) fig2, ax2 = plt.subplots(figsize=(9, 7)) for reg, c in region_colors.items(): m = df['地域'] == reg ax2.scatter(x[m], y[m], c=c, s=60, alpha=0.85, label=reg, zorder=3) xl = np.array([x.min(), x.max()]) sl, ic, rr, pp, _ = stats.linregress(x, y) ax2.plot(xl, sl*xl + ic, 'k--', lw=1.5, label=f'回帰直線 r={r:.3f}') for name in ['東京都','愛知県','群馬県','三重県','大阪府']: row = df[df['都道府県'] == name].iloc[0] ax2.annotate(name.replace('県','').replace('都','').replace('府',''), (row['総人口']/10000, row['外国人人口割合']), fontsize=9, xytext=(4, 4), textcoords='offset points') ax2.set_xlabel('総人口 [万人]', fontsize=12) ax2.set_ylabel('外国人人口割合 [%]', fontsize=12) ax2.set_title('図2:総人口と外国人人口割合(2019年・47都道府県)', fontsize=13) ax2.legend(fontsize=9, loc='upper left') ax2.grid(True, alpha=0.3) fig2.tight_layout() fig2.savefig(os.path.join(FIG_DIR, '2021_H4_fig2.png'), bbox_inches='tight') plt.close(fig2) print(f"人口 × 外国人人口割合 r = {r:.3f} (p = {p:.2e})") |
人口 × 外国人人口割合 r = 0.676 (p = 1.81e-07)
stats.pearsonr は相関係数 r と p値を同時に返します。r は関係の強さ・向き、p は「無相関という偶然で説明できるか」を示す別々の情報です。人口の効果が大きいままでは他の要因が埋もれる。そこで原論文は人口400万人超の9都道府県(北海道・埼玉・千葉・東京・神奈川・愛知・大阪・兵庫・福岡)を除外し、残り38都道府県で6つの要因と外国人人口割合の相関を調べた。原論文が立てた仮説は次の3系統である。
湿度・日本語教育・完全失業率・製造品出荷額の各データは SSDSE-B-2026 に収録がなく、本教材では再計算できない。以下の図4は原論文5章が報告した相関係数をそのまま並べたもの(再計算ではない)である。
| 要因 | 原論文の図 | 相関係数 r | 判定 | 本教材 |
|---|---|---|---|---|
| 年平均気温 | 図8 | 0.16 | ほとんど相関なし | 図3で再現(0.111) |
| 年平均相対湿度 | 図9 | −0.47 | 負の相関 | 報告値 |
| 日本語教育機関数 | 図10 | 0.54 | 正の相関 | 報告値 |
| 日本語常勤教師数 | 図11 | 0.54 | 正の相関 | 報告値 |
| 完全失業率 | 図12 | −0.26 | 弱い負の相関 | 報告値 |
| 製造品出荷額 | 図13 | 0.72 | 強い正の相関 | 報告値 |
※原論文5.1の一覧表は図番号を「図7〜12」と表記しているが、本文および図の見出し(図8〜13)と対応させると上表のとおり。数値・符号・判定は原論文の報告値。
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | big = ['北海道','埼玉県','千葉県','東京都','神奈川県','愛知県','大阪府','兵庫県','福岡県'] sub = df[~df['都道府県'].isin(big)].copy() # 人口400万人以下の38都道府県 rt, pt = stats.pearsonr(sub['年平均気温'], sub['外国人人口割合']) fig3, ax3 = plt.subplots(figsize=(9, 6.5)) for reg, c in region_colors.items(): m = sub['地域'] == reg ax3.scatter(sub.loc[m,'年平均気温'], sub.loc[m,'外国人人口割合'], c=c, s=55, alpha=0.85, label=reg, zorder=3) xl = np.array([sub['年平均気温'].min(), sub['年平均気温'].max()]) sl, ic, *_ = stats.linregress(sub['年平均気温'], sub['外国人人口割合']) ax3.plot(xl, sl*xl + ic, 'k--', lw=1.5, label=f'回帰直線 r={rt:.3f}') ax3.set_xlabel('年平均気温 [℃]', fontsize=12) ax3.set_ylabel('外国人人口割合 [%]', fontsize=12) ax3.set_title('図3:年平均気温と外国人人口割合(人口400万人以下・2019年)', fontsize=13) ax3.legend(fontsize=9) ax3.grid(True, alpha=0.3) fig3.tight_layout() fig3.savefig(os.path.join(FIG_DIR, '2021_H4_fig3.png'), bbox_inches='tight') plt.close(fig3) print(f"除外した人口400万人超の県: {len(big)}件 → 残り {len(sub)}都道府県") print(f"年平均気温 × 外国人人口割合 r = {rt:.3f} (p = {pt:.3f})") |
除外した人口400万人超の県: 9件 → 残り 38都道府県 年平均気温 × 外国人人口割合 r = 0.111 (p = 0.508)
~df['列'].isin(リスト) の ~ は「否定」。「リストに含まれない行だけ」を素早く抽出できます。128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | # ★ 以下は原論文(5章)が報告した相関係数の「そのまま可視化」であり再計算ではない reported = [ ('年平均気温', 0.16), ('年平均相対湿度', -0.47), ('日本語教育機関数', 0.54), ('日本語常勤教師数', 0.54), ('完全失業率', -0.26), ('製造品出荷額', 0.72), ] labels = [x[0] for x in reported] vals = [x[1] for x in reported] colors = ['#C62828' if v < 0 else '#1565C0' for v in vals] fig4, ax4 = plt.subplots(figsize=(9, 5.5)) ypos = range(len(labels)) ax4.barh(list(ypos), vals, color=colors, edgecolor='white') for i, v in enumerate(vals): ax4.text(v + (0.02 if v >= 0 else -0.02), i, f'{v:+.2f}', va='center', ha='left' if v >= 0 else 'right', fontsize=11) ax4.axvline(0, color='black', lw=0.8) ax4.set_yticks(list(ypos)); ax4.set_yticklabels(labels, fontsize=11) ax4.set_xlim(-0.7, 0.9) ax4.set_xlabel('外国人人口割合との相関係数 r(原論文の報告値)', fontsize=11) ax4.set_title('図4:外国人人口割合と各要因の相関(原論文 報告値の可視化・再計算ではない)', fontsize=12) ax4.grid(True, axis='x', alpha=0.3) fig4.tight_layout() fig4.savefig(os.path.join(FIG_DIR, '2021_H4_fig4.png'), bbox_inches='tight') plt.close(fig4) for lb, v in reported: print(f" {lb}: r = {v:+.2f}") |
年平均気温: r = +0.16 年平均相対湿度: r = -0.47 日本語教育機関数: r = +0.54 日本語常勤教師数: r = +0.54 完全失業率: r = -0.26 製造品出荷額: r = +0.72
ax.barh は横棒グラフ。ラベルが長い項目や、正負が混在する係数の比較には縦棒より横棒が読みやすくなります。| 手法 | 主な知見 | 限界 |
|---|---|---|
| 相関分析(人口) | 人口 × 外国人人口割合 r=0.661(本教材 0.676) | 大都市に強く引っ張られる |
| 相関分析(6要因・人口400万人以下) | 製造品出荷額0.72/日本語教育0.54/湿度−0.47 | n=38の小標本、相関=因果ではない |
| 気候の解釈 | 気温はほぼ無相関(0.16) | 年平均気温は四季の気候差を捉えきれない |
| データ | 出典 |
|---|---|
| SSDSE-B 都道府県データ(2019年断面) | 独立行政法人統計センター SSDSE(教育用標準データセット)2026年版 |
| 総人口・日本人人口 | 総務省 人口推計(SSDSE-B 収録) |
| 年平均気温 | 気象庁 過去の気象データ(SSDSE-B 収録) |
| 外国人人口・湿度・日本語教育・完全失業率・製造品出荷額 | 法務省・総務省・文化庁・経済産業省(原論文が使用。図4は報告値を引用) |
本教育用コードは SSDSE-B-2026.csv の実データを使用(合成データ不使用)。図2・図3の相関は実再現、図4は原論文報告値の可視化(再計算ではない)。
この研究は相関分析だけで構成されています。だからこそ「相関と因果の混同」に最も注意が必要です。読む前にも読んだ後にも目を通してみてください。
本文で見慣れない言葉が出てきたら、ここに戻って確認してください。
この論文は相関分析と、それを支える散布図・回帰直線・箱ひげ図だけで構成されています。手法ごとに「何のためか」「どう読むか」「注意点」を解説します。
scipy.stats.pearsonr で r と p値を計算する。ax.scatter で点を描き、stats.linregress の傾き・切片で直線を重ねる。この研究をさらに発展させる3つの方向性です。「今回わかったこと(X)」から「次に検証すべき仮説(Y)」を立て、「具体的に何をするか(Z)」まで考えてみましょう。
学んだだけでは身につきません。実際に手を動かすのが最強の学習方法です。本論文のスクリプトをベースに挑戦してみてください。
本論文の相関分析は、研究だけでなく行政・企業・NPOの現場でも広く使われています。
この論文を読んで初心者が抱きやすい疑問に、教育的観点から答えます。
この論文を理解できたか、クリックで確認しましょう。間違えても解説が出ます。
このページの分析は、この画面の中でそのまま実行できます。
Python をインストールする必要も、CSV をダウンロードする必要もありません。
下のセルの 「▶ ブラウザで実行」 を上から順に押すか、
「▶ 最初から全部実行」 で一気に流してください。
表示されるのは、本文の図表とまったく同じ計算の結果です
(動かしているのは再現スクリプト code/2021_H4_katsuyo.py そのもの)。
コードは書き換えられます。「✏️ 書き換える」で数字や変数を変えて ▶ を押すと、 結果がどう変わるかをその場で確かめられます(元に戻すボタンつき)。 ページを開いた時点で裏で実行環境の準備が始まっているので、待ち時間はほとんどありません。 初回だけ実行環境の取得にインターネット接続が必要です。