この教材は、元データが公開されていないため再計算ができません。原論文が論文中に報告した数値をたどって図表にし、「その数値からどこまで言えるか」を読み解く形で学びます。数値そのものは原論文からの引用であり、この教材が計算したものではありません。
| 原論文が使ったデータ | SSDSE-A・SSDSE-B・国勢調査・日本の地域別将来推計人口・松山市ホームページ・jSTAT MAP・経済センサス・本校全校生徒アンケート 分析単位:その他 中核手法:相関分析 |
|---|---|
| この教材が使うデータ | CSV は読み込まない(原論文が報告した数値をそのまま図表化して読み解く) |
| 原論文(PDF) | 高校生と高齢者の利用で中央商店街を活性化しよう!! 特別賞/田中千遥・玉井菜実(愛媛県立松山南高等学校) |
原論文と同じ粒度のデータは、この教材にも同梱しています。これを読み込めば、原論文と同じ細かさで分析をやり直せます(下の「🐍 ブラウザで動かす」でコードを書き換えて試せます)。ただし原論文が使った項目がすべて収録されているとは限りません。足りない項目は、上の「できないこと」に書いた出典から取ってくる必要があります。
▶ ここに書いてある分析は、ページ下部の「🐍 ブラウザで動かす」でそのまま実行できます(インストール不要)。動かしているのは code/2020_H5_2_shorei.py(215 行)そのものです。
著者が通う愛媛県立松山南高校の近くには、松山市の中央商店街(銀天街・大街道)がある。 近年この商店街では空き店舗が増え、通行量が減り、活気不足だと感じられていた。 そこで、中央商店街の現状と周辺住民の状況をデータで分析し、活性化のための具体的な施策を考えることを目的とした研究である。
まず「なぜ商店街に活気がないのか」を感覚ではなくデータでとらえることが出発点になる。 通行量が減る → 店の売上が下がる → 空き店舗が増える → さらに人が来なくなる、という悪循環が起きていないかを、公開データで確かめていく。
SSDSE-2020A/B 時系列の可視化 構成比・帯グラフ エリア分析(GIS) アンケート集計
本研究は、教育用標準データセット SSDSE と、複数の公的データ・独自アンケートを組み合わせている。
| データ | 内容・年度 | 出典 |
|---|---|---|
| SSDSE-2020A(市区町村データ) | 松山市の総人口・年少/生産年齢/老年人口(2015) | 国勢調査 |
| SSDSE-2020B(都道府県・時系列) | 愛媛県の人口(2010, 2015 ほか) | 国勢調査 |
| 追加:人口の長期推移 | 愛媛県・松山市(1980〜2010) | 国勢調査 |
| 追加:将来推計人口 | 2020〜2045(5年刻み) | 国立社会保障・人口問題研究所「日本の地域別将来推計人口」 |
| 中央商店街 通行量 | 平成18〜26年度 | 松山市HP「中心市街地の現状と課題」 |
| 空き店舗率 | 平成10〜25年度 | 松山市HP「中心市街地の現状と課題」 |
| エリア分析レポート | 半径500m〜1km 圏(H27) | e-Stat 地図で見る統計(jSTAT MAP) |
| 商店街利用アンケート | 令和元年度・全校生徒1,023人 | 本校独自アンケート |
まず松山市の公開データから、中央商店街の通行量と空き店舗率の推移を確認する。 原論文によれば、通行量は平成19年度から平成26年度にかけて 26,765人減少し、 空き店舗率は平成10年度から平成25年度にかけて約7倍に増加した。 通行量が減って売上が下がり、空き店舗が増える——という悪循環に陥っている。
目的:空き店舗率が「市全体・中心市街地・中央商店街」でどう違い、どのように悪化してきたかを一目で比べたい。 そのために:まず分析の土台(ライブラリ・日本語フォント・図の保存先)を用意する。
1 2 3 4 5 6 7 8 9 10 11 12 13 | import os import numpy as np import pandas as pd import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt plt.rcParams['font.family'] = 'Hiragino Sans' # Windowsは 'Yu Gothic' plt.rcParams['axes.unicode_minus'] = False plt.rcParams['figure.dpi'] = 150 FIG_DIR = 'html/figures' os.makedirs(FIG_DIR, exist_ok=True) |
print しません。以降で使う準備(フォント設定・保存先フォルダの作成)が整っただけです。matplotlib.use('Agg') — 画面表示せず図をPNGファイルに保存するための指定。plt.rcParams['font.family'] = 'Hiragino Sans' — グラフの日本語が豆腐(□)にならないようにするフォント指定(Windowsなら Yu Gothic)。os.makedirs(FIG_DIR, exist_ok=True) — 図の保存先 html/figures/ を作成(既にあってもエラーにしない)。matplotlib.use('Agg') は import matplotlib.pyplot の前に呼ぶのが安全です。そのため次を実行:原論文 図2 の空き店舗率(3系列×9時点)の報告値をそのまま表にして、増加の大きさを数値で確認する。
14 15 16 17 18 19 20 21 22 23 24 | # 原論文 図2 の報告値をそのまま定義(%) years = ['H10', 'H12', 'H13', 'H15', 'H17', 'H19', 'H21', 'H23', 'H25'] vac = pd.DataFrame({ '市全体': [6.7, 10.4, 11.1, 11.9, 10.6, 14.2, 15.5, 16.0, 16.2], '中心市街地': [5.2, 5.4, 5.7, 6.2, 7.6, 8.9, 11.2, 13.8, 14.0], '中央商店街': [1.6, 2.6, 2.4, 2.3, 2.7, 6.5, 9.8, 9.6, 11.3], }, index=years) print(vac.to_string()) ratio = vac['中央商店街'].iloc[-1] / vac['中央商店街'].iloc[0] print(f"中央商店街: {ratio:.1f}倍 ≒ 約7倍") |
市全体 中心市街地 中央商店街 H10 6.7 5.2 1.6 H12 10.4 5.4 2.6 H13 11.1 5.7 2.4 H15 11.9 6.2 2.3 H17 10.6 7.6 2.7 H19 14.2 8.9 6.5 H21 15.5 11.2 9.8 H23 16.0 13.8 9.6 H25 16.2 14.0 11.3 中央商店街: 7.1倍 ≒ 約7倍
pd.DataFrame({...}, index=years) — 3系列(市全体/中心市街地/中央商店街)×9時点の報告値をそのまま表にした。vac['中央商店街'].iloc[-1] / vac['中央商店街'].iloc[0] — 最後(H25=11.3)÷最初(H10=1.6)=7.1倍。原論文の「約7倍」と一致する。.iloc[-1] は「末尾の要素」。マイナス添字で後ろから数えられます。そのため次を実行:表だけでは推移の形が見えないので、3系列の折れ線グラフにして各点に報告値を印字する。
25 26 27 28 29 30 31 32 33 34 35 | fig, ax = plt.subplots(figsize=(10, 5.5)) colors_v = {'市全体': '#1F3B99', '中心市街地': '#D63FA0', '中央商店街': '#E8A33D'} markers = {'市全体': 'o', '中心市街地': 's', '中央商店街': '^'} for col in vac.columns: ax.plot(years, vac[col], marker=markers[col], color=colors_v[col], linewidth=2, markersize=7, label=col) for x, y in zip(years, vac[col]): # 各点に報告値を印字 ax.annotate(f'{y}', (x, y), textcoords='offset points', xytext=(0, 7), ha='center', fontsize=8) ax.set_ylabel('空き店舗率(%)'); ax.set_ylim(0, 18); ax.legend() fig.savefig(f'{FIG_DIR}/2020_H5_2_fig1.png', bbox_inches='tight') |
print はしません。下の図1が生成されます。ax.plot(...) を呼び、色とマーカーを分けて重ねている。for x, y in zip(years, vac[col]) で、各点の真上に報告値(例: 11.3)を annotate で印字。zip(a, b) は2つのリストを同時に回せます。座標と値をペアで扱うときに便利。
次に「商店街の周りにはどんな人が住んでいるのか」を調べる。原論文は、銀天街・大街道の境目あたりを中心に 半径約500m のエリア(原論文 図4 の地図)について、e-Stat 地図で見る統計(jSTAT MAP)で エリア分析レポートを作成し、年齢別人口・世帯人員・産業構成を調べた。
目的:周辺エリアは松山市全体と比べて「高齢者が多いのか」「単身世帯が多いのか」を、報告値で端的に比べたい。 そのために:原論文の本文に明記された代表値(高齢者割合・単身世帯割合)を表にして比較する。
36 37 38 39 40 41 | # 原論文 図5・図6 の報告値(本文に明記された代表値のみ) area = pd.DataFrame({ '65歳以上人口の割合': [30, 25], '単身世帯の割合': [65, 40], }, index=['商店街周辺エリア', '松山市全体']) print(area.to_string()) |
65歳以上人口の割合 単身世帯の割合 商店街周辺エリア 30 65 松山市全体 25 40
さらに原論文は、周辺エリアの産業別事業所数を松山市・愛媛県と比較している(図7)。 周辺エリアは第3次産業(サービス業)の割合が特に大きく、その内訳(図8)では 宿泊業・飲食サービス業の割合が大きい。商店街周辺は「食べる・過ごす」ためのお店が中心の街だとわかる。 図7・図8 は多カテゴリの帯グラフで各値が明記されていないため、グラフは原論文参照とした。
原論文は、銀天街・大街道を中心に半径約1kmの範囲に、本校を含め高校が7校集まり、 約7,000人の高校生がいることを地図(図9)と表で示している。 毎日この地域に通う高校生は、商店街にとって大きな潜在的利用者だ。
目的:「どの高校に何人いるか」を一覧し、周辺の高校生数の大きさを実感したい。 そのために:原論文 図9 の表の報告値を定義し、横棒グラフにする。
42 43 44 45 46 47 48 | # 原論文 図9 の報告値(半径約1km圏の7校) schools = pd.DataFrame({ '高校': ['松山東', '松山南', '松山工業', '松山商業', '聖カタリナ学園', '済美', '松山東雲'], '全校生徒数': [1050, 1050, 950, 950, 950, 1800, 300], }) print(schools.to_string(index=False)) print(f"合計: 約{schools['全校生徒数'].sum():,}人") |
高校 全校生徒数
松山東 1050
松山南 1050
松山工業 950
松山商業 950
聖カタリナ学園 950
済美 1800
松山東雲 300
合計: 約7,050人{値:,} の , は3桁区切りの書式。7050 が 7,050 と表示されます。
「高校生は中央商店街に何を望んでいるのか」を調べるため、著者は本校全校生徒1,023人にアンケートを実施した。 結果、半数以上が中央商店街の利用は週1回以下で、「自宅と商店街の方向が逆」「部活が忙しい」「行く理由がない」といった声が多かった。
目的:高校生の利用頻度の分布を一目でつかみたい。 そのために:原論文 図10 の報告値(%)を円グラフにする。
49 50 51 52 53 54 55 56 57 58 59 | # 原論文 図10(利用頻度, n=1023)の報告値を円グラフに freq_labels = ['毎日', '週4〜6回', '週1〜3回', 'それ以下', '通らない'] freq_vals = [3, 3, 9, 57, 28] # %(合計100) fig, ax = plt.subplots(figsize=(7, 7)) ax.pie(freq_vals, labels=[f'{l}\n{v}%' for l, v in zip(freq_labels, freq_vals)], startangle=90, counterclock=False, wedgeprops=dict(edgecolor='white', linewidth=1.5)) fig.savefig(f'{FIG_DIR}/2020_H5_2_fig4.png', bbox_inches='tight') print('週1回以下(それ以下+通らない)=', 57 + 28, '%') |
週1回以下(それ以下+通らない)= 85 %
print は集計値のみ出力します。counterclock=False と startangle=90 で、円グラフを12時から時計回りに描けます。
著者は「高校生に気軽に来てもらうために、空き店舗に自習室を設置してはどうか」と考え、 その賛否と、払ってもよい料金を追加でアンケートした。
そのため次を実行:自習室の賛否(図11)と希望価格帯(図12)の報告値を確認し、「賛成は多いが、お金は払いたくない」という現実を数値でとらえる。
60 61 62 63 64 | # 図11(自習室の利用希望)と 図12(希望価格帯)の報告値 wish_vals = [58, 42] # はい / いいえ price_vals = [2, 4, 19, 16, 59] # 1000円以上 … 払いたくない print('自習室に賛成:', wish_vals[0], '%') print('料金を払いたくない:', price_vals[-1], '%(最多)') |
自習室に賛成: 58 % 料金を払いたくない: 59 %(最多)
以上の分析——少子高齢化、通行量減少と空き店舗増加、周辺に多い高齢者・単身世帯、約7,000人の高校生、そして「近いのに使っていない」高校生——から、 著者は高校生・高齢者・単身世帯をターゲットに、次の施策を提案した。
愛媛県・松山市の人口減少と、中央商店街の通行量減少・空き店舗増加をデータで確認し、 著者の通う高校の近くにある中央商店街が活気不足であることを示した。 そのうえで高校生・高齢者・単身世帯をターゲットにした具体的な活性化施策を提案した。
本ページはこの研究を「報告値の忠実な可視化」として再現した。統計モデルによる因果推論は行われていないが、 身近な課題を多面的なデータで裏づけ、当事者(高校生)目線で施策に落とし込んだ点に価値がある。 審査コメントの「データの調査にとどまっている」という指摘は、次の一歩——施策の効果測定——への宿題でもある。
このページの図は原論文の報告値をそのまま可視化したものです。そのため、外部データのダウンロードは不要で、スクリプトだけでそのまま動きます。
html/figures/ に自動保存されます。
この研究のデータ・図を読むときに、特に気をつけたいポイントを手法別に整理する。
この論文を読むうえで押さえておきたい用語をまとめた。
本研究は高度なモデルを使わず、目的に応じて「基本的な可視化」を的確に選んでいる。手法ごとに要点と注意点を示す。
この研究を出発点に、さらに深められる方向を挙げる。
再現スクリプトを少し書き換えて、手を動かして理解を深めよう。
colors_v と markers を編集して、図1 の見た目を変えてみよう。凡例と対応しているか確認。vac['中央商店街'].iloc[-1] - vac['中央商店街'].iloc[0] で H10→H25 の増加ポイントを出し、3系列で比べよう。freq_vals をまとめ直し、2区分の円グラフを描く。約85% がひと目でわかる図になる。color をリストで指定)。ターゲット校を目立たせよう。「エリアの特性を集計し、基本的な図で示す」やり方は、実務で広く使われている。
この研究とページについての疑問に答える。
この論文を理解できたか、クリックで確認しましょう。間違えても解説が出ます。
このページの分析は、この画面の中でそのまま実行できます。
Python をインストールする必要も、CSV をダウンロードする必要もありません。
下のセルの 「▶ ブラウザで実行」 を上から順に押すか、
「▶ 最初から全部実行」 で一気に流してください。
表示されるのは、本文の図表とまったく同じ計算の結果です
(動かしているのは再現スクリプト code/2020_H5_2_shorei.py そのもの)。
コードは書き換えられます。「✏️ 書き換える」で数字や変数を変えて ▶ を押すと、 結果がどう変わるかをその場で確かめられます(元に戻すボタンつき)。 ページを開いた時点で裏で実行環境の準備が始まっているので、待ち時間はほとんどありません。 初回だけ実行環境の取得にインターネット接続が必要です。