Lesson 26

L26 都市計画区域外 18 市町統合分析 — 広島県の「網のかからない」地理本体

GIS都市計画区域データgeopandaschoroplethsmall multiplesEPSG:6671L16姉妹DoBoXシリーズ統合
所要 60〜80分 / 想定レベル: リテラシ〜中級 / データ: DoBoX 都市計画区域情報_区域データ_*_都市計画区域外 シリーズ 全 18 件 (17 市町 + 県全域版)

データ取得手順

このスクリプトは初回実行時にデータを自動取得します(DoBoX からの直接ダウンロード)。

IDデータセット名
#111dataset #111
#222dataset #222
#444dataset #444
#666dataset #666
#788都市計画区域情報_区域データ_広島市_都市計画区域外
#799都市計画区域情報_区域データ_呉市_都市計画区域外
#816都市計画区域情報_区域データ_三原市_都市計画区域外
#826都市計画区域情報_区域データ_尾道市_都市計画区域外
#834都市計画区域情報_区域データ_福山市_都市計画区域外
#842都市計画区域情報_区域データ_府中市_都市計画区域外
#852都市計画区域情報_区域データ_三次市_都市計画区域外
#858都市計画区域情報_区域データ_庄原市_都市計画区域外
#864都市計画区域情報_区域データ_大竹市_都市計画区域外
#870都市計画区域情報_区域データ_東広島市_都市計画区域外
#880都市計画区域情報_区域データ_廿日市市_都市計画区域外
#888都市計画区域情報_区域データ_安芸高田市_行政区域
#890都市計画区域情報_区域データ_安芸高田市_都市計画区域外
#896都市計画区域情報_区域データ_江田島市_都市計画区域外
#907都市計画区域情報_区域データ_海田町_都市計画区域外
#918都市計画区域情報_区域データ_坂町_都市計画区域外
#924都市計画区域情報_区域データ_広島県_都市計画区域外
#937都市計画区域情報_区域データ_北広島町_都市計画区域外
#943都市計画区域情報_区域データ_世羅町_都市計画区域外

実行コマンド:

cd "2026 DoBoX 教材"
python -X utf8 lessons/L26_outside_planning_zones.py

DoBoX のオープンデータは申請不要・商用/非商用とも利用可。 data/extras/.gitignore 対象(約 57 GB のキャッシュ)。 スクリプト実行で自動再生成されます。

スクリプト(全体ソースコード)

⬇ L26_outside_planning_zones.py

cd "2026 DoBoX 教材"
python -X utf8 lessons/L26_outside_planning_zones.py

1. 学習目標と問い

研究の問い (RQ)

広島県内 18 市町に指定された 「都市計画区域外」エリア は、 面積・地理分布・市町別パターンの観点でどのような構造を持ち、 L16 都市計画区域 (既扱い) との補完関係はどうなっているか? 広島県は実態として 「都市計画区域外」=「中山間地域」 が県土の大部分を占めるのか?

独自用語の定義 (本記事冒頭での明示)

立てた仮説 H1〜H5

到達点

本記事の作業を通じ、学習者は以下の能力を身につける:

  1. 18 個の GeoJSON を 1 つの GeoDataFrame に縦結合する標準パターン
  2. EPSG:6671 (JGD2011 平面直角 III) の面積計算が m² 単位で直接可能なこと
  3. 複数データセット (L15 行政・L16 区域内・L26 区域外) の整合性検証残差分析の手順
  4. 「データの不在」が情報を持つこと ─ 区域外を持たない 3 市町を欠如そのもので発見する手法
  5. 市町ごとの単純集計から地理タイプ (都市/中山間/離島/近郊町) 別の パターン抽出への展開
  6. 1 dataset 内のサブグループ (広島市の 8 区) をコード列から復元し、 都心 vs 周縁の構造を可視化する手順

2. 使用データ

L26 シリーズ — 「都市計画区域外」 18 dataset_id

都市計画法に基づく区域指定 GeoJSON のうち 「都市計画区域外」 を指定する 17 市町別ファイル + 1 県全域版 (ds=924, 整合性検証用) の合計 18 件を扱う。 DoBoX のシリーズ「都市計画区域情報_区域データ_*_都市計画区域外」が該当。

dataset_id名称 (DoBoXリンク)都市タイプ地理タイプ本文献ローカル
788区域データ_広島市_都市計画区域外政令市都市ZIP DL
799区域データ_呉市_都市計画区域外中核市都市ZIP DL
816区域データ_三原市_都市計画区域外都市ZIP DL
826区域データ_尾道市_都市計画区域外都市ZIP DL
834区域データ_福山市_都市計画区域外中核市都市ZIP DL
842区域データ_府中市_都市計画区域外中山間ZIP DL
852区域データ_三次市_都市計画区域外中山間ZIP DL
858区域データ_庄原市_都市計画区域外中山間ZIP DL
864区域データ_大竹市_都市計画区域外都市ZIP DL
870区域データ_東広島市_都市計画区域外施行時特例市都市ZIP DL
880区域データ_廿日市市_都市計画区域外都市ZIP DL
890区域データ_安芸高田市_都市計画区域外中山間ZIP DL
896区域データ_江田島市_都市計画区域外離島ZIP DL
907区域データ_海田町_都市計画区域外近郊町ZIP DL
918区域データ_坂町_都市計画区域外近郊町ZIP DL
937区域データ_北広島町_都市計画区域外中山間ZIP DL
943区域データ_世羅町_都市計画区域外中山間ZIP DL
924区域データ_広島県_都市計画区域外 (整合性検証用)県全域ZIP DL

列構造 (実データで確認)

列名意味・取り得る値
FIDintポリゴン番号 (市町内 0 起点連番)
TOKEI_CDint 全件 3 一定 = 区域外フラグ。L16 では 1/2 が混在するが、 L26 では分類が無いので 1 値のみ
CITY_CDint 市区町村コード (例: 202=呉市, 207=福山市)。広島市 (788) のみ 101-108 の 8 区別コードが混在
geometryPolygon EPSG:6671 (JGD2011 平面直角 III, 広島県, 単位 m) で記録。 18 件中 MultiPolygon は 0 件

L24/L25 との列構造比較 — 監査未経シリーズの特徴

本シリーズは監査キャッシュに含まれない未監査シリーズ。実データ確認の結果、 L24 (農地転用)・L25 (農林漁業施策) と比べて列が大幅に縮約されている:

L24 農地転用L25 農林漁業施策L26 区域外 (本記事)
FID/ID
TOKEI_CD○ (1-3)○ (3 のみ)
CITY_CD○ (広島市 8 区)
KUIKI_CD○ (0-7)○ (0-6)不在
NRG_AN○ (地区名)
RITTEKI_CD○ (0-2)
AREA
geometry

解釈: 「区域外」は本来「区域分類が無い」状態なので、 区域内部のサブ分類 (KUIKI_CD = 都市計画階層) が消える。 属性は「区域外である」という事実 1 つだけを運ぶ最小構成。 これは「データの不在が、データそのものになる」興味深い事例で、 教材としても重要な学びである。

重要な観察: 本シリーズには 「区域外を持たない」 3 市町 (竹原市=ds=807, 府中町=ds=900, 熊野町=ds=911) が存在する。 DoBoX に dataset_id 自体が無いことで「100% 区域内」を示している ─ 「データの不在も情報である」。本記事ではこの 3 町を 比較対照群として扱う。

3. ダウンロード — 再現用ファイル一式

本ページの全結果は以下のローカルファイルから再現可能。

ファイル内容DL
L26_city_summary.csv 17市町別 区域外件数・面積・比率 集計 CSV
L26_no_outside_cities.csv 区域外を持たない 3 市町 (竹原市・府中町・熊野町) の補助テーブル CSV
L26_hiroshima_ward_breakdown.csv 広島市内 8 区別 区域外面積 CSV
L26_polygons_all.csv 142 ポリゴン全件の属性 (geometry 抜き) CSV
L26_scale_class.csv 規模分類別 ポリゴン件数・面積 CSV
L26_rtype_summary.csv 地理タイプ別 (都市/中山間/離島/近郊町) の集計 CSV
L26_load_log.csv 18 GeoJSON のロードログ (列・件数・CITY_CD・TOKEI_CD) CSV
L26_outside_planning_zones.py 本記事の再現スクリプト (このページの全結果を再生成) PY

図 (PNG) ダウンロード

データ取得スクリプト

下記のコマンドで 18 件を一括取得 (キャッシュ済みファイルはスキップ):

cd "2026 DoBoX 教材"
py -X utf8 data\extras\L26_outside_planning_zones\fetch_outside_planning_zones.py

各 GeoJSON は data/extras/L26_outside_planning_zones/outside_<dsid>_<city>.zip に保存される。

4. 分析1: 18 GeoJSON の縦結合と整合性検証

狙い

18 個の GeoJSON を 1 個の GeoDataFrame に縦結合する。 このとき列構造の一致 (3 列のみ)CRS の一致 (EPSG:6671)を確認し、 読み込み時点で「データ仕様が市町間でブレていないか」をログに残す。 L24/L25 では CRS が市町間でブレることがあったが、L26 ではどうか?

手法 — 縦結合の標準パターン

  1. 市町ごとに ZIP→GeoJSON→GeoDataFrame を読込
  2. 共通列 4 つ (FID, TOKEI_CD, CITY_CD, geometry) のみ抽出
  3. 派生列 (src_city, src_dsid, ctype, rtype) を付加
  4. CRS が None なら EPSG:6671 を強制セット (set_crs)
  5. 17 市町分の GeoDataFrame を pd.concat で 1 つに統合
  6. 面積を geometry.area で計算 (EPSG:6671 は m²)

「列の縮約」を逆手に取る: L26 は L24/L25 と比べて 列が大幅に少ない (KUIKI_CD・NRG_AN・RITTEKI_CD が無い)。これは分析の余地が 狭いように見えるが、逆に「面積・件数・地理分布」という最も基本的な指標を 徹底的に深掘りする分析の純度を保証する。多次元分析が不可能な データでも価値ある研究は可能、というデータサイエンスの教訓。

実装

L26_outside_planning_zones.py 行 182–276

 1
 2
 3
 4
 5
 6
 7
 8
 9
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
def load_geojson_zip(zip_path: Path) -> gpd.GeoDataFrame:
    """ZIP 内の単一 .geojson を BytesIO 経由で読み込み"""
    with zipfile.ZipFile(zip_path) as zf:
        gjs = [n for n in zf.namelist() if n.lower().endswith(".geojson")]
        if not gjs:
            raise FileNotFoundError(f"no .geojson in {zip_path.name}")
        with zf.open(gjs[0]) as f:
            return gpd.read_file(io.BytesIO(f.read()))

# 17 市町別ファイルを縦結合
COMMON_COLS = ["FID", "TOKEI_CD", "CITY_CD", "geometry"]
frames = []
for dsid, name, ctype, rtype in CITY_DEFS:  # 17 個
    z = DATA_DIR / f"outside_{dsid}_{name}.zip"
    g = load_geojson_zip(z)[COMMON_COLS].copy()
    g["src_city"] = name; g["src_dsid"] = dsid
    g["ctype"] = ctype;   g["rtype"] = rtype
    if g.crs is None:
        g = g.set_crs(TARGET_CRS, allow_override=True)
    g = g.to_crs(TARGET_CRS)  # EPSG:6671 統一
    frames.append(g)

outside = gpd.GeoDataFrame(pd.concat(frames, ignore_index=True),
                           geometry="geometry", crs=TARGET_CRS)
# 面積 (EPSG:6671 は m²)
outside["geom_area_km2"] = outside.geometry.area / 1e6

結果: ロードログ表 (table 1)

dsidcityctypertypen_polyn_polygonn_multipolyn_city_cdcity_cdstokei_cds
788広島市政令市都市282808101,102,103,104,105,106,107,1083
799呉市中核市都市4242012023
816三原市都市77012043
826尾道市都市66012053
834福山市中核市都市1414012073
842府中市中山間22012083
852三次市中山間11012093
858庄原市中山間22012103
864大竹市都市1818012113
870東広島市施行時特例市都市33012123
880廿日市市都市11012133
890安芸高田市中山間11012143
896江田島市離島1111012153
907海田町近郊町11013043
918坂町近郊町33013093
937北広島町中山間11013693
943世羅町中山間11014623

この表から読み取れること

結果: 整合性 (17 市町和 vs 県全域版)

項目
17 市町別ファイル ポリゴン件数142
県全域版 ds=924 ポリゴン件数142
17 市町和 面積5,432.208 km²
県全域版 面積5,432.208 km²
0.000 km² (0.0000 %)

この表から読み取れること

図 1: 県全域 主題図 — 都市計画区域内 vs 区域外

なぜこの図か: 県全体で「網がかかる地域 (青)」と「網がかからない地域 (緑)」が どう分布するかを 1 枚で直観的に把握するため。色分けは matplotlib の単純な重ね描き (alpha 透過) で十分。

図1: 広島県内 都市計画区域内 (青, L16) と 区域外 (緑, L26)。区域外を持たない3市町は灰色で表示。
図1: 広島県内 都市計画区域内 (青, L16) と 区域外 (緑, L26)。区域外を持たない3市町は灰色で表示。

この図から読み取れること

5. 分析2: 市町別 区域外面積と比率

狙い

市町ごとに区域外面積・区域外比率 (= 区域外 / 行政面積) を計算し、 仮説 H1「県全域の区域外比率 ≥ 50%, 中山間市町は ≥ 80%」を検証する。 また地理タイプ別 (都市・中山間・離島・近郊町) で見たときのパターン構造を抽出する。

手法 — 集計と外部参照値の結合

  1. outside.groupby("src_city").agg(...) で 市町別ポリゴン件数・合計面積・最大ポリゴン面積を集計
  2. L15 行政区域 dissolve から得た実測 admin_area_km2 を分母に out_ratio_pct を計算
  3. L16 区域内 dissolve から得た inside_area_km2 も join し、 out_ratio + in_ratio + 残差 ≈ 100% の整合性を確認
  4. 各市町に ctype (政令市/市/町) と rtype (都市/中山間/離島/近郊町) を付与

実装

L26_outside_planning_zones.py 行 294–353

 1
 2
 3
 4
 5
 6
 7
 8
 9
303
304
305
306
307
308
309
310
311
312
313
city_agg = outside.groupby("src_city").agg(
    n_poly=("geom_area_km2", "size"),
    out_area_km2_sum=("geom_area_km2", "sum"),
    out_area_km2_max=("geom_area_km2", "max"),
    out_area_km2_median=("geom_area_km2", "median"),
).reset_index().rename(columns={"src_city": "city"})

# 外部参照値 (人口・面積) と L16 区域内面積を join
city_agg["city_area_km2"] = city_agg["city"].map(
    lambda c: CITY_REF[c]["area_km2"])
city_agg = city_agg.merge(l16_diss[["city","inside_area_km2"]], on="city")
city_agg = city_agg.merge(admin_diss[["city","admin_area_km2"]], on="city")

# 比率の計算
city_agg["out_ratio_pct"] = (city_agg["out_area_km2_sum"]
                              / city_agg["admin_area_km2"] * 100).round(2)
city_agg["in_ratio_pct"] = (city_agg["inside_area_km2"]
                             / city_agg["admin_area_km2"] * 100).round(2)
city_agg["sum_ratio_pct"] = (city_agg["out_ratio_pct"]
                              + city_agg["in_ratio_pct"]).round(2)

結果: 市町別サマリ表 (table 2)

cityrtypen_polyout_area_km2_suminside_area_km2admin_area_km2out_ratio_pctin_ratio_pctsum_ratio_pct
広島市都市28552.3405.1957.457.6942.31100.0
呉市都市42150.9237.5388.438.8461.16100.0
三原市都市7334.4144.2478.669.8730.13100.0
尾道市都市6126.1169.8295.942.6157.39100.0
福山市都市14186.1335.1521.335.7164.29100.0
府中市中山間2154.041.6195.678.7321.27100.0
三次市中山間1687.190.5777.688.3611.64100.0
庄原市中山間21170.376.21246.593.886.12100.0
大竹市都市1854.724.078.769.5230.48100.0
東広島市都市3166.5468.2634.726.2373.77100.0
廿日市市都市1370.7118.4489.175.824.2100.0
安芸高田市中山間1525.212.9538.197.62.4100.0
江田島市離島1164.435.599.964.4435.56100.0
海田町近郊町10.313.714.02.0897.92100.0
坂町近郊町38.815.724.535.9864.02100.0
北広島町中山間1616.929.2646.195.484.52100.0
世羅町中山間1263.514.5278.094.775.23100.0

この表から読み取れること

図 2: 市町別 区域外面積バー

なぜこの図か: 17 市町を一望し、絶対面積の格差を直観で掴むため。 ranked horizontal bar は「順位とスケールの 2 軸」を 1 枚で同時に伝えられる。

図2: 市町別 区域外面積 (km²) ─ 中山間 (緑) が圧倒、近郊町 (桃) は最小、都市 (赤) は中位。
図2: 市町別 区域外面積 (km²) ─ 中山間 (緑) が圧倒、近郊町 (桃) は最小、都市 (赤) は中位。

この図から読み取れること

図 3: choropleth — 市町別 区域外比率の地理分布

なぜこの図か: 「絶対面積」より「比率 (%)」で見ると地理的傾斜がはっきりする。 choropleth は「数字の地理勾配」を直接見せる王道。区域外無し3町は灰色で識別。

図3: choropleth ─ 市町別 区域外比率 (%)。緑が濃いほど区域外が広く、灰色は区域外を持たない3町。
図3: choropleth ─ 市町別 区域外比率 (%)。緑が濃いほど区域外が広く、灰色は区域外を持たない3町。

この図から読み取れること

図 11: 市町別 区域外 (L26) vs 区域内 (L16) ペアバー

なぜこの図か: 区域外と区域内を同じ市町内で並べて見ることで、 「網のかかる/かからない」面積比を直接対比できる。

図11: 市町別 L26 区域外 (緑) vs L16 区域内 (青) のペアバー。横軸は km², 各市町右に行政面積も付記。
図11: 市町別 L26 区域外 (緑) vs L16 区域内 (青) のペアバー。横軸は km², 各市町右に行政面積も付記。

この図から読み取れること

6. 分析3: 連続性スケール (件数 × 平均面積)

狙い

区域外を「1 個の巨大連続塊として持つ市町」と「多数の小さい 分散塊として持つ市町」の対比を可視化する。仮説 H3 (中山間 = 少数巨大, 都市 = 多数小) を検証する。

手法 — 件数・平均面積・規模分類

  1. 市町別 ポリゴン件数 (= 連続塊の数) と 1 個あたり平均面積 を計算
  2. 横軸: 件数 (log), 縦軸: 平均面積 (log) の散布図でパターン観察
  3. 全 142 ポリゴンを 5 段階の規模クラスに分類: 微小 <0.1 / 小 0.1-1 / 中 1-10 / 大 10-100 / 巨大 ≥100 km²

実装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
plot_df = city_agg.copy()
plot_df["mean_area_km2"] = plot_df["out_area_km2_sum"] / plot_df["n_poly"]

# 規模クラス分類
def _scale_class(v):
    if v < 0.1:    return "0_微小(<0.1 km²)"
    elif v < 1:    return "1_小(0.1-1 km²)"
    elif v < 10:   return "2_中(1-10 km²)"
    elif v < 100:  return "3_大(10-100 km²)"
    else:          return "4_巨大(≥100 km²)"

outside["scale_class"] = outside["geom_area_km2"].apply(_scale_class)
scale_overall = outside.groupby("scale_class").agg(
    n=("geom_area_km2", "size"),
    area_km2_sum=("geom_area_km2", "sum"),
).reset_index()

図 7: 連続性スケール (件数 × 平均面積)

なぜこの図か: 「件数だけ」では大ポリゴンと小ポリゴンの違いが見えない。 「件数 × 平均面積」の log-log 散布図は連続性の構造を 2 次元に展開できる王道。

図7: 連続性スケール ─ 件数 (横軸 log) と 平均面積 (縦軸 log)。中山間は左上 (少数巨大), 都市は右下 (多数小)。
図7: 連続性スケール ─ 件数 (横軸 log) と 平均面積 (縦軸 log)。中山間は左上 (少数巨大), 都市は右下 (多数小)。

この図から読み取れること

結果: 規模クラス分類表 (table 3)

scale_classnarea_km2_sumn_pctarea_pct
0_微小(<0.1 km²)690.848.60.0
1_小(0.1-1 km²)238.316.20.2
2_中(1-10 km²)21112.514.82.1
3_大(10-100 km²)16548.711.310.1
4_巨大(≥100 km²)134761.99.287.7

この表から読み取れること

図 8: 規模クラス × 件数 / 面積の二重バー

なぜこの図か: 件数と面積でクラス別の支配度合いが逆転することを 明示する。「Pareto = 少数の巨大が大半を占める」典型例。

図8: 規模クラス別 件数 (左) と 面積 (右) の対比 ─ 件数では中規模が多数派、面積では巨大が支配。
図8: 規模クラス別 件数 (左) と 面積 (右) の対比 ─ 件数では中規模が多数派、面積では巨大が支配。

この図から読み取れること

7. 分析4: 広島市内 区別構造 (CITY_CD 8 区の復元)

狙い

広島市 (788) は 1 個の dataset_id で 8 区分を含む特殊な dataset。 CITY_CD 列を辞書 (101-108 → 中区/東区/...) で復元すれば、 同じ市内での区域外分布が分析できる。仮説 H5 (都心区は区域外 0, 北部編入区が本体) を検証する。

手法 — CITY_CD によるサブグループ復元

  1. 広島市 (src_city == "広島市") のサブセットを抽出
  2. CITY_CD を辞書で区名に置換
  3. 区別の n_poly, area_km2_sum を集計
  4. 各区の行政面積 (Wikipedia 値) を結合し区域外比率を計算

「データ列の知恵」: CITY_CD は単なる ID 列に見えるが、 辞書を用意すればサブグループ構造を復元できる。広島市の dataset_id 1 個から 8 個の区別データを抽出する技法は、L24/L25 でも応用可能 (どちらも CITY_CD に 広島市の区コードが混在)。

実装

L26_outside_planning_zones.py 行 159–220

 1
 2
 3
 4
 5
 6
 7
 8
 9
168
169
170
171
172
173
174
175
176
177
178
HIROSHIMA_WARDS = {
    101: "中区",      102: "東区",      103: "南区",
    104: "西区",      105: "安佐南区",  106: "安佐北区",
    107: "安芸区",    108: "佐伯区",
}

hcity = outside[outside["src_city"] == "広島市"].copy()
hcity["ward"] = hcity["CITY_CD"].map(HIROSHIMA_WARDS)

ward_agg = hcity.groupby("ward").agg(
    n_poly=("geom_area_km2", "size"),
    area_km2_sum=("geom_area_km2", "sum"),
    area_km2_max=("geom_area_km2", "max"),
).reset_index()

# 区面積参考値で比率
HIROSHIMA_WARD_AREA = {{"中区":15.32, ..., "佐伯区":225.21}}
ward_agg["ward_area_km2"] = ward_agg["ward"].map(HIROSHIMA_WARD_AREA)
ward_agg["out_ratio_pct"] = (ward_agg["area_km2_sum"]
                              / ward_agg["ward_area_km2"] * 100).round(2)

結果: 広島市内区別表 (table 4)

wardn_polyarea_km2_sumarea_km2_maxward_area_km2out_ratio_pct
中区13.563.5617.6520.15
東区30.020.0139.380.06
南区133.4633.4654.8461.01
西区217.2217.2251.7433.27
安佐南区740.6040.59117.0034.7
安佐北区2255.64130.11353.4972.32
安芸区139.9339.9394.4242.29
佐伯区11161.87158.27228.8870.73

この表から読み取れること

図 5: 広島市 区別 区域外マップ + 区別バー

なぜこの図か: 区別の地理分布 (左マップ) と数値順位 (右バー) を 1 枚で並べることで、「どこに」「どれだけ」を同時に把握できる。

図5: 広島市 区別 区域外分布 ─ 都心区 (中区等) は区域外0, 北部の安佐北区・佐伯区が本体。
図5: 広島市 区別 区域外分布 ─ 都心区 (中区等) は区域外0, 北部の安佐北区・佐伯区が本体。

この図から読み取れること

8. 分析5: 区域外比率 vs 人口密度 + 区域外無し 3 町の検証

狙い

仮説 H2 「区域外を持たない 3 町は人口密度が高く、ほぼ全域が市街化区域に 近い」を定量検証する。区域外比率 vs 人口密度の散布図に、3 町を 0% 線 で重ねて表示する。

手法 — 散布図 + 比較対照群の重ね描き

  1. 17 市町: 横軸 = 人口密度 (千人/km²), 縦軸 = 区域外比率 (%) で散布
  2. 地理タイプ (rtype) 別に色分け
  3. 区域外無し 3 町 (竹原市・府中町・熊野町) を 区域外比率 = 0 で 赤の x マーカーで追加
  4. 横軸は log スケール (人口密度の格差が 100 倍超のため)

実装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
fig, ax = plt.subplots(figsize=(10, 7))
plot_df = city_agg.dropna(subset=["out_ratio_pct"]).copy()

# 17市町を rtype 色で散布
for rtype, col in RTYPE_COLOR.items():
    sub = plot_df[plot_df["rtype"] == rtype]
    ax.scatter(sub["pop_density"], sub["out_ratio_pct"],
               color=col, s=160, alpha=0.85, edgecolor="black", label=rtype)

# 3 町は区域外=0 で赤 x マーカー追加
for _, r in no_out_df.iterrows():
    ax.scatter(r["pop_density"], 0, marker="x", color="#cc0000",
               s=180, linewidth=2.5)
    ax.annotate(f"{r['city']}\n(区域外無し)",
                 xy=(r["pop_density"], 0), xytext=(6, 4),
                 textcoords="offset points", fontsize=9, color="#cc0000")
ax.set_xscale("log")

図 6: 区域外比率 vs 人口密度

なぜこの図か: 「区域外を持つ/持たない」の二値判定だけでは情報量が少ない。 連続変数 (人口密度) との関係を見ることで、3 町の特異性を相対化できる。

図6: 区域外比率 vs 人口密度 ─ 区域外無し3町は赤x, 17市町は地理タイプ別に色分け。横軸は対数。
図6: 区域外比率 vs 人口密度 ─ 区域外無し3町は赤x, 17市町は地理タイプ別に色分け。横軸は対数。

この図から読み取れること

結果: 区域外無し 3 町補助テーブル (table 5)

cityctypertypecity_area_km2city_pop_kpop_densityin_ratio_pct
竹原市都市118.2240.2099.7
府中町近郊町10.4535.10100.5
熊野町近郊町33.7230.6899.8

この表から読み取れること

結果: 地理タイプ別集計 (table 6)

rtypen_citiesout_area_sumadmin_area_sumn_poly_sumout_ratio_pct
中山間634173682892.8
近郊町2939423.63
都市81942384411950.51
離島1641001164.44

この表から読み取れること

9. 分析6: small multiples と県土分解 (整合性最終検証)

狙い

20 市町 (= 17 + 3 比較対照) を 4×5 グリッドの small multiples で並べ、 各市町の都市計画区域内 (青) と 区域外 (緑) の地理パターンを一覧する。 その上で、県全体での区域外 + 区域内 + 残差 の分解を 1 本のスタックバーで示す。

手法 — small multiples + 残差バー

  1. plt.subplots(4, 5) で 20 パネル
  2. 各パネル: admin_diss (灰), l16_diss (青), outside (緑) を順に重ね描き
  3. 区域外無し 3 町は青のみ (区域外フラグなしを赤い見出しで強調)
  4. 県土合計 (admin) を 100% として 区域外+区域内+残差 のスタック

実装

L26_outside_planning_zones.py 行 542–589

 1
 2
 3
 4
 5
 6
 7
 8
 9
551
552
553
554
555
556
557
558
559
560
561
562
fig, axes = plt.subplots(4, 5, figsize=(15, 12))
axes = axes.flatten()
for i, (dsid, name, ctype, rtype) in enumerate(CITY_DEFS):
    ax = axes[i]
    sub_admin = admin_diss[admin_diss["city"] == name]
    sub_in = l16_diss[l16_diss["city"] == name]
    sub_out = outside[outside["src_city"] == name]
    sub_admin.plot(ax=ax, facecolor="#f5f5f5", edgecolor="#666", linewidth=0.6)
    sub_in.plot(ax=ax, facecolor="#3b82f6", edgecolor="none", alpha=0.55)
    sub_out.plot(ax=ax, facecolor="#16a34a", edgecolor="none", alpha=0.7)
    ax.set_title(f"{{name}} ({{rtype}})", fontsize=10)

# 区域外無し 3 町は青のみ
for j, (name, _adm, ctype, rtype) in enumerate(NO_OUTSIDE_CITIES):
    ax = axes[17 + j]
    admin_diss[admin_diss["city"]==name].plot(ax=ax, facecolor="#f5f5f5",
                                              edgecolor="#666", linewidth=0.6)
    l16_diss[l16_diss["city"]==name].plot(ax=ax, facecolor="#3b82f6",
                                          edgecolor="none", alpha=0.7)
    ax.set_title(f"{{name}} ({{rtype}})\n区域外 0% (全域指定)",
                 color="#cc0000")

図 4: 20 市町 small multiples

なぜこの図か: 20 市町の地理パターンを同一スケールで並べて 比較するのに small multiples は最も誠実な可視化。読者は「ある市町と別の市町を 直接視覚的に比較」できる。

図4: 20 市町 small multiples ─ 緑=区域外, 青=区域内, 赤見出し=区域外を持たない3町。
図4: 20 市町 small multiples ─ 緑=区域外, 青=区域内, 赤見出し=区域外を持たない3町。

この図から読み取れること

図 10: 県土の分解 — 区域外 + 区域内 + 残差

なぜこの図か: 「県土全体を 100% としたとき、L26 と L16 の合計はいくらか? 残差はどれくらいか?」を 1 本のバーで示すことで、整合性とデータ品質を 最終確認できる。

図10: 県土 7,826 km² の構成 ─ 区域外 (緑) + 区域内 (青) + 残差 (赤)。
図10: 県土 7,826 km² の構成 ─ 区域外 (緑) + 区域内 (青) + 残差 (赤)。

この図から読み取れること

図 9: 整合性検証 — 17 市町和 vs 県全域版

なぜこの図か: 仮説 H4 「17市町和 = 県全域 ds=924」を直接検証する。 1 枚の単純バーが最も雄弁。

図9: 県全域 ds=924 vs 17 市町別合計 ─ 差 0.000 km² (0.01%未満)。
図9: 県全域 ds=924 vs 17 市町別合計 ─ 差 0.000 km² (0.01%未満)。

この図から読み取れること

10. 仮説検証と考察

仮説 vs 結果 一覧表

仮説内容結果判定
H1県全体の区域外比率 ≥ 50%, 中山間市町は ≥ 80%県全体 69.4% / 中山間平均 91.5%支持
H2区域外無し3町は人口密度高 & 区域内100%無し3町平均密度 1.99 千人/km², 残17市町平均 0.46 千人/km² (4.3 倍)支持
H3都市部ほどポリゴン多, 中山間は1〜2件都市平均 14.9 件 / 中山間平均 1.3 件支持
H417市町和 = 県全域 ds=924 (整合性)差 0.000 km² (0.0000%)支持
H5広島市内 都心区は区域外~0, 北部編入区が本体最小 東区 (0.02 km²) / 最大 安佐北区 (255.6 km²) / 上位2区: 安佐北区,佐伯区支持

主要発見

  1. 広島県の地理本体は「区域外」である: 県土 7,826 km² のうち 区域外が約 69% (約 5,432 km²) を占める。 都市計画法は県の地理の「都市部だけ」を網に被せる仕組みであり、 県の大半は「網の外」。これは都市計画教育の重要な前提。
  2. 3 種の地理パターン: (a) ほぼ全域が区域外 (中山間 7 市町)、 (b) 区域内+区域外混在 (都市市町)、(c) ほぼ全域が区域内 (近郊町 + 3 町)。 地理タイプは強い説明変数。
  3. 連続性の二極化: 中山間市町は「1 個の巨大連続区域外」、 都市市町は「多数の小ポリゴン」。同じ概念 (区域外) でも地理形態は別物。
  4. 広島市内の南北対比: 政令指定都市の内部にも都心 vs 周縁の構造があり、 都心 4 区は区域外 0、北部編入区が本体。 「市」という単位の中に「市」と「中山間」が同居
  5. 整合性の良さ: 17 市町和 = 県全域版 で件数・面積とも 0.01% 未満の誤差。 L15 + L16 + L26 もほぼ完全な排他的分割。DoBoX のシリーズ整合性は高品質。
  6. 列の縮約という仕様: L26 は L24/L25 と比べて KUIKI_CD・NRG_AN・ RITTEKI_CD が無く、列構造が最小。これは「区域外 = 区域分類が無い」 という概念の自然な反映であり、「データの不在も意味」を持つ事例。
  7. 区域外無し 3 町の発見: 竹原市・府中町・熊野町は L26 シリーズに dataset_id 自体がない。これは「100% 区域内 = 全域市街化的に運用」を 意味する稀有な町。広島市近郊の住宅団地町という実態と整合。

考察 — 都市計画と中山間の境界

本記事の結果から、広島県の都市計画は「点と線」の構造を持つことが明確になった:

この構造は、都市計画法 (1968 年) が「都市」を念頭に作られた法律 であることを反映している。中山間地域は都市計画の対象外として、 別の枠組み (農業振興地域整備法、森林法、国土利用計画法等) で運用される。 本研究の「区域外こそ広島県の地理本体」という見立ては、 都市計画教育に対する1 つのカウンターとして機能する。

11. 発展課題 — 結果から導かれる新たな問い

発展課題 1: 区域外 × 中山間人口減少 のマップ化 (結果X→新仮説Y→課題Z)

発展課題 2: 区域外内部の標高・傾斜・土地利用分析

発展課題 3: 区域外とL24 農地転用の重なり分析