Lesson 44

L44 高潮浸水想定区域 3 件統合分析 — 広島県沿岸の「海起源浸水」を 3 規模シナリオで読み解く

高潮浸水想定区域水防法瀬戸内海沿岸防災統合分析geopandasShapefile
所要 60〜90 分 / 想定レベル: リテラシ〜中級 (geopandas/Shapefile/空間結合の基礎) / データ: DoBoX dataset 43, 44, 45 (高潮浸水想定区域情報 3 件) — Shapefile 計 5.5 MB

データ取得手順

⚠️ このスクリプトは自動取得に対応していません。以下のデータセットを DoBoX から手動でダウンロードし、data/extras/ 以下に保存してください。

IDデータセット名
#43高潮浸水想定区域情報_30年確率
#44高潮浸水想定区域情報_伊勢湾台風規模
#45高潮浸水想定区域情報_想定最大規模
#222dataset #222
#333dataset #333
#666dataset #666

実行コマンド:

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

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

学習目標と問い

本レッスンでは、広島県オープンデータ DoBoX が公開する 高潮浸水想定区域情報 3 dataset (id = 43, 44, 45) を統合し、 広島県沿岸の「海起源浸水」を 3 規模シナリオで読み解く。

独自用語の定義 (本記事内での使用)

主 RQ (研究の問い)

広島県沿岸の高潮浸水想定区域 3 dataset は、地理範囲・浸水深ランク構成・ 市町カバレッジでどう違い、3 規模をクロスして見ると、県沿岸の 「海起源浸水の盲点」はどこに浮かび上がるか?

仮説 H1〜H6 (本記事で検証する)

到達点

3 dataset を空間結合・深ランク集計・市町別オーバーレイした上で、 6 仮説を量的に検証する。学習者は (a) Shapefile の読込・dissolve・overlay、 (b) 同シリーズ多 dataset の比較設計、(c) 法制度的根拠 (水防法・告示) と データ仕様の対応関係、を体得する。

厳密性の宣言: 本記事は L4-L11 (河川浸水) ・L8 (河川 × 津波 × 盛土) と厳密に独立。河川浸水 (流域降雨) と高潮浸水 (海面異常上昇) は 水文機構が異なる別災害として扱う。津波 (海底地震) も別機構である。

使用データ

本記事は DoBoX の「高潮浸水想定区域情報」シリーズ 3 dataset を統合する。 カタログ上は告示日と告示思想の異なる 3 件として登録されている:

表 (1) — 3 dataset の仕様サマリ

dataset_id シナリオ rid 告示日 polygons rank 種数 ZIP MB 総浸水 km²
43 30 年確率 39 2017-04-21 1046 4 0.78 30.3
44 伊勢湾台風規模 69 2017-04-21 106 5 1.56 45.1
45 想定最大規模 70 2021-08-03 7 7 4.13 242.9

この表から読み取れること: (1) ZIP サイズはシナリオ規模に概ね比例 (0.8 → 1.6 → 4.1 MB)。 (2) 同じ告示日の 30y/isewan に対し、max は 4 年新しい (2017→2021)。 (3) max は dissolve 済みの 7 polygons のみ ⇔ 30y は 1,046 polys に分散。 これは「max は rank ごとの dissolve 配信」「30y は未統合の細分化配信」 という配信形態の違いを示し、データ仕様自体が告示思想の違いを反映する。

表 (2) — 浸水深ランクの凡例 (本記事独自配色)

rank コード 深さ範囲 色 (本記事) 30y 出現 isewan 出現 max 出現
01 0〜0.5 m #bee2ff
02 0.5〜1.0 m #87c4f0
03 1.0〜3.0 m #56a4dc
04 3.0〜5.0 m #1c63a4
05 5.0〜10.0 m #0e4282
06 10.0 m〜 #4a1280
07 家屋倒壊等氾濫想定区域 #cf222e

この表から読み取れること: rank 06 (10m 以上) は max のみ存在。 rank 07 (家屋倒壊等氾濫想定区域) も max のみで初出現する。 告示思想の進化が rank の細分化と概念拡張として直接観察できる。

形式の詳細

ダウンロード(再現用データ・中間データ・図)

HTML から直接以下を取得できる:

(A) DoBoX 直リンク (3 dataset)

シナリオdatasetresource_download (ZIP)サイズ
30 年確率 dataset 43 直 DL (rid 39) 0.78 MB
伊勢湾台風規模 dataset 44 直 DL (rid 69) 1.56 MB
想定最大規模 dataset 45 直 DL (rid 70) 4.13 MB

(B) PowerShell 一括取得 (再現用)

cd "2026 DoBoX 教材"
mkdir -Force data\extras\L44_storm_surge
iwr "https://hiroshima-dobox.jp/resource_download/39" -OutFile "data\extras\L44_storm_surge\30year.zip"
iwr "https://hiroshima-dobox.jp/resource_download/69" -OutFile "data\extras\L44_storm_surge\isewan.zip"
iwr "https://hiroshima-dobox.jp/resource_download/70" -OutFile "data\extras\L44_storm_surge\max.zip"
# 展開後、各 ZIP 内の .shp/.dbf/.shx/.prj/.cpg を sub-dir に配置

(C) 中間データ・図 (本記事生成物の直リンク)

分析 1: 規模別 総浸水面積 — 階段状の拡大

狙い (RQ ↔ 仮説 H1)

3 シナリオ (30y, isewan, max) の総浸水面積を比較し、規模拡大時に 面積が線形に拡大するのか、階段状にジャンプするのかを検証する。 仮説 H1 は「max は ise の 5 倍以上、30y の 7 倍以上 = ジャンプ型」と予測。

手法

各 Shapefile を geopandas.read_file() で読み、 EPSG:6671 (m単位) に投影変換した後、geometry.area で ポリゴン面積を算出して合計する。dissolve はランク列単位で行う (同 rank の全 polygon を 1 MultiPolygon に統合) ことで、 重複する重なり面積を二重カウントしない。

事前計算 (要件 S 対策): max シナリオは 7 polygon (rank ごと dissolve 済) だが、 内部的に複雑な MultiPolygon を含むため dissolve に ~30 秒、 市町別 overlay に ~10 秒かかる。本記事は _l44_build_cache.py で これらを事前計算し、本スクリプトはキャッシュ GPKG/CSV を読むだけにすることで 1 分以内完走を実現している (要件 S)。

実装コード

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import geopandas as gpd
from pathlib import Path

CACHE = Path("data/extras/L44_storm_surge/_cache")
TARGET_CRS = "EPSG:6671"  # JGD2011 平面直角座標系第 III 系 (m)

# キャッシュ GPKG (rank 別 dissolve 済) を読み込み
diss = {{
    "30y":    gpd.read_file(CACHE / "diss_30y.gpkg").to_crs(TARGET_CRS),
    "isewan": gpd.read_file(CACHE / "diss_ise.gpkg").to_crs(TARGET_CRS),
    "max":    gpd.read_file(CACHE / "diss_max.gpkg").to_crs(TARGET_CRS),
}}

# 各シナリオの総面積 (km²) を計算
for sc, g in diss.items():
    total_km2 = g.geometry.area.sum() / 1e6
    print(f"{{sc:6s}}: {{total_km2:8.2f}} km²  ({{len(g)}} ranks)")

結果の図

図1 を選んだ理由: 3 値の比較なら棒グラフが最も明快。倍率 (×8倍) を 矢印注記で重ねることで「線形ではなくジャンプである」ことを視覚的に強調する。 表の数値だけでは「拡大した」という事実は伝わるが、 「どのくらい想定外なのか」の直感は得られない。

図1: 3 シナリオ別 総浸水想定面積
図1: 3 シナリオ別 総浸水想定面積

図1 から読み取れること:

結果の表 (1) — シナリオ別 基本指標

シナリオ dataset_id 告示 総浸水 km² rank 種数 最大 rank 最多面積 rank 最多面積 km² rank7_km²
30 年確率 43 2017-04 30.33 4 4 1 19.63 0.00
伊勢湾台風規模 44 2017-04 45.08 5 5 4 20.72 0.00
想定最大規模 45 2021-08 242.88 7 7 5 99.24 0.01

表 (1) から読み取れること:

結果の表 (2) — 拡大ジャンプの定量化

指標
30y -> isewan (km²) 14.75
isewan -> max (km²) 197.80
max / 30y 倍率 8.01
max / isewan 倍率 5.39

表 (2) から読み取れること: max - isewan の差分 (197.8 km²) は 30y - 0 (=30y そのもの, 30.3 km²) の 6.5 倍。 規模を 1 段階上げただけで、30y シナリオ全体を上回る面積が新規追加される。 高潮シナリオの保守化は非線形で、社会の備えが追いつかない構造的リスクを示唆する。

分析 2: 浸水深ランク構成 — 「深まりながら広がる」

狙い (RQ ↔ 仮説 H2, H5, H6)

規模拡大に伴い、新たに浸水想定される領域は「浅い」のか「深い」のか。 H2 は「30y では浅 rank01 が最多、max では深 rank04 以上が最多」と予測。 H5 は「rank07 (家屋倒壊等) は max のみ」、H6 は「max は rank 種数も最多」を予測。

手法 — Stacked Bar による rank 構成比較

各シナリオで rank ごとの面積を集計し、stacked bar として並べる。 stacked bar は「全体の中の構成比」を示すのに最適 (3 シナリオ × 7 rank の 2 次元データを 1 図で示せる)。pie chart でも構成比は示せるが、 3 シナリオ間の比較を同一スケールで行うには stacked bar の方が圧倒的に読みやすい。

実装コード

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import numpy as np

# 各シナリオの rank 別 km² を抽出 (cache から)
sc_keys = ["30y", "isewan", "max"]
xs = np.arange(len(sc_keys))

bottom = np.zeros(len(sc_keys))
for rk in range(1, 8):
    vals = []
    for sc in sc_keys:
        g = diss[sc]
        m = g[g["rank_int"] == rk]
        vals.append(float(m.area_km2.sum()))   # rank ごと面積 (km²)
    if max(vals) == 0:
        continue
    plt.bar(xs, vals, bottom=bottom,
            color=RANK_COLOR[rk], label=f"rank {{rk:02d}}")
    bottom += np.array(vals)

結果の図

図2 を選んだ理由: stacked bar は構成比 + 規模感を 1 図で示せる (円グラフだと 3 シナリオの比較は 3 円が並ぶ形になり面倒)。 同一の y 軸スケールで 3 シナリオを並べることで、規模ジャンプも 構成シフトも同時に観察できる。

図2: 3 シナリオ × 7 浸水深ランクの面積構成
図2: 3 シナリオ × 7 浸水深ランクの面積構成

図2 から読み取れること:

結果の表 — rank ピボット

シナリオ rank1 rank2 rank3 rank4 rank5 rank6 rank7
30 年確率 19.63 6.47 3.28 0.94 0.00 0.00 0.00
伊勢湾台風規模 3.94 5.39 15.02 20.72 0.01 0.00 0.00
想定最大規模 4.84 4.03 13.42 87.82 99.24 33.53 0.01

表から読み取れること: 30y は 19.6 km² が rank01 のみで占有 (全 30y の 65%)、 max は rank04 が 87.8 km² (全 max の 36%) が 最多。max は rank05/06/07 にも面積を持ち多段階深ランクになっている。 これは「max は単に広い」のではなく「深い領域の存在を新たに記述する」 告示思想の違いを定量的に示している。

分析 3: 重ね合わせマップ — 県沿岸の地理分布

狙い

3 シナリオを 1 枚の地図に重ねることで、どの沿岸エリアが各規模で 浸水想定されるかを地理的に確認する。さらに max シナリオ単独で 深ランク主題図を描き、「家屋倒壊等氾濫想定区域 (rank07)」の 位置を可視化する。

手法 — 多レイヤ choropleth + 主題図

位置情報があれば地図化必須 (要件 T)。本分析は 2 種類の地図を作る: (a) 重ね合わせマップ — 30y/isewan/max を半透明 alpha=0.55 で重ね描画。 外側に大きい polygon が、内側に小さい polygon が見える階層構造になる。 (b) 主題図 — max のみを rank ごとに色塗りし、深い領域がどこにあるかを示す。

実装コード

L44_storm_surge.py 行 1011–1049

 1
 2
 3
 4
 5
 6
 7
 8
 9
1020
1021
1022
1023
1024
1025
1026
1027
1028
import geopandas as gpd
import matplotlib.pyplot as plt
from matplotlib.patches import Patch

fig, ax = plt.subplots(figsize=(13, 7))

# 背景: 県内行政界
admin_diss.plot(ax=ax, color="#f0f0f0", edgecolor="#aaa", linewidth=0.4)

# 3 シナリオを薄→濃で重ね
for sc in ["30y", "isewan", "max"]:
    diss[sc].plot(ax=ax,
                  color=SCENARIOS[sc]["color"],
                  edgecolor="none",
                  alpha=0.55)

ax.set_aspect("equal")
ax.set_title("3 シナリオ 重ね合わせマップ")

結果の図 (1) — 県全域 3 シナリオ重ね

図3: 高潮浸水想定区域 3 シナリオ 重ね合わせマップ
図3: 高潮浸水想定区域 3 シナリオ 重ね合わせマップ

図3 から読み取れること:

結果の図 (2) — 想定最大規模 浸水深 主題図

図4: 想定最大規模 (dataset 45) の浸水深ランク主題図
図4: 想定最大規模 (dataset 45) の浸水深ランク主題図

図4 を選んだ理由: max シナリオ単独で深ランクごとに色を変えると、 「どこが浅く、どこが深いか」が地図上で直接読める。 3 シナリオを重ねた図3 では各シナリオの境界しか見えないが、 主題図 (choropleth) は連続値の地理パターンを見るのに最適。

図4 から読み取れること:

分析 4: 沿岸 2 大湾ズーム — 「広がりながら深まる」を確認

狙い (RQ ↔ 仮説 H4)

福山湾と広島湾の 2 大湾を 3 シナリオでズームし、規模拡大に伴う 空間パターンの変化を視覚的に追う。仮説 H4 は「福山港が 3 シナリオ全てで 1 位」を予測。

手法 — Small multiples + bbox ズーム

同じ縮尺・同じ凡例で 3 シナリオを並べるsmall multiples 構図。 bbox は admin_diss.total_bounds から計算し、2km マージンを付与。 同じレンズで 3 時点を見せることで規模の進化を直感的に伝える。

実装コード

L44_storm_surge.py 行 1077–1109

 1
 2
 3
 4
 5
 6
 7
 8
 9
1086
1087
1088
1089
1090
1091
fig, axes = plt.subplots(1, 3, figsize=(14, 5.2))
# bbox 計算 (福山港 = CITY_CD 207)
xmin, ymin, xmax, ymax = admin_diss[admin_diss["CITY_CD"] == 207].total_bounds
margin = 2000   # 2km
xmin -= margin; ymin -= margin; xmax += margin; ymax += margin

for ax, sc in zip(axes, ["30y", "isewan", "max"]):
    admin_diss.plot(ax=ax, color="#f0f0f0", edgecolor="#aaa")
    g = diss[sc].sort_values("rank_int")
    for _, row in g.iterrows():
        gpd.GeoDataFrame([row], crs=g.crs).plot(
            ax=ax, color=row["color"], edgecolor="none", alpha=0.85)
    ax.set_xlim(xmin, xmax); ax.set_ylim(ymin, ymax)
    ax.set_aspect("equal")
    ax.set_title(SCENARIOS[sc]["jp"])

結果の図 (1) — 福山湾ズーム

図5: 福山湾 3 シナリオ ズームマップ
図5: 福山湾 3 シナリオ ズームマップ

図5 から読み取れること:

結果の図 (2) — 広島湾ズーム

図6: 広島湾 3 シナリオ ズームマップ
図6: 広島湾 3 シナリオ ズームマップ

図6 から読み取れること:

分析 5: 市町別ランキング — 福山港の優位性

狙い (RQ ↔ 仮説 H4, H3)

3 シナリオの市町別浸水面積を集計し、(a) どの市町が最も大きいか(b) シナリオ間で順位が変わるか(c) max でのみ追加される市町は どこかを量的に検証する。

手法 — 行政界 GeoJSON との空間結合

L15 で既知の行政界 GeoJSON (data/extras/L15_admin_zones/admin_922_広島県.zip) を 読込、CITY_CD で dissolve して 27 市町ポリゴンを得る (=広島市 8 区 + 14 市 + 5 町)。 各シナリオの dissolve 済みポリゴンと geopandas.sjoin(predicate=intersects) で候補ペアを抽出し、ペアごとに shapely.intersection で 正確な交差面積を計算する。

STEP1/STEP2 構造:
  • STEP 1 — sjoin で「重なる可能性のある (rank, city) ペア」のみ抽出 (高速)
  • STEP 2 — 抽出されたペアだけ正確な intersection を計算 (低速だが対象数が小さい)
両方とも _l44_build_cache.py で実行され、結果は per_city_rank.csv に保存。本記事の本体スクリプトは CSV を読むだけ。

実装コード (キャッシュビルダ部分の抜粋)

L44_storm_surge.py 行 1149–1185

 1
 2
 3
 4
 5
 6
 7
 8
 9
1158
1159
1160
1161
1162
1163
# STEP 1: sjoin で候補ペアを抽出
sj = gpd.sjoin(g_dissolved,                       # rank ごと dissolve 済
               admin_diss[["CITY_CD", "geometry"]],
               how="inner",
               predicate="intersects")

# STEP 2: ペアごと正確な交差面積を計算
results = []
for _, sjr in sj.iterrows():
    rk, ccd = sjr["SINSUIRANK"], sjr["CITY_CD"]
    poly_rk = g_dissolved[g_dissolved["SINSUIRANK"] == rk].geometry.iloc[0]
    poly_ci = admin_diss[admin_diss["CITY_CD"] == ccd].geometry.iloc[0]
    inter = shapely.intersection(poly_rk, poly_ci)
    results.append({{"rank": rk, "city_cd": ccd,
                    "area_km2": inter.area / 1e6}})

結果の図 (1) — 市町別 3 シナリオ 比較バー

図8 を選んだ理由: horizontal bar は市町名の長い文字列を見やすく 表示でき、3 シナリオの値を並べることで「シナリオ間で順位がどう変わるか」が 直観的に読める。choropleth は地理を示すには良いが、定量的な順位は バーグラフが優れる。

図8: 市町別 3 シナリオ 浸水想定面積 比較 (上位15)
図8: 市町別 3 シナリオ 浸水想定面積 比較 (上位15)

図8 から読み取れること:

結果の図 (2) — 市町コロプレス (max シナリオ)

図7: 想定最大規模 市町別 浸水想定面積コロプレス
図7: 想定最大規模 市町別 浸水想定面積コロプレス

図7 から読み取れること:

結果の表 — 市町別 上位10

CITY_CD 市町 沿岸 30 年確率 km² 伊勢湾規模 km² 想定最大 km² max - 30y max / 30y
207 福山市 True 2.50 0.00 56.50 54.00 22.59
202 呉市 True 6.23 0.00 28.94 22.71 4.64
205 尾道市 True 2.39 0.00 21.01 18.62 8.78
204 三原市 True 0.75 0.00 17.96 17.22 24.11
103 広島市南区 True 2.94 14.31 16.18 13.24 5.50
104 広島市西区 True 3.86 9.42 14.32 10.47 3.71
101 広島市中区 True 3.69 10.16 11.66 7.97 3.16
215 江田島市 True 0.52 0.00 10.54 10.02 20.29
213 廿日市市 True 0.31 1.76 9.25 8.95 30.32
203 竹原市 True 3.35 0.00 8.61 5.25 2.57

表から読み取れること: max/30y 倍率の列が ∞ となるのは 「30y では浸水想定なし、max で初めて指定された市町」。 これらは仮説 H3 (カバレッジ拡大) の直接証拠。 有限値の中で倍率が大きい市町は「規模拡大の感度が高い市町」= 湾奥地形・干拓地・島嶼など物理的増幅条件が強い。

分析 6: 規模拡大倍率 — 「max で初めて姿を現す盲点」

狙い (RQ ↔ 仮説 H3, H6)

各市町について(a) max の浸水想定面積(b) max/30y 倍率を 2 軸で 散布させ、「max で初めて指定された市町 (盲点市町)」を浮き上がらせる。

手法 — log scale 散布 + 沿岸/内陸 色分け

x 軸 = max km²、y 軸 = max/30y 倍率 (log 10)。30y=0 (max のみ) の 市町は倍率が ∞ になるため、三角マーカー (▲) で y=50 (cap 値) に表示し 他と差別化。色分けは沿岸 (赤) / 内陸 (青) の二分類。

実装コード

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
fig, ax = plt.subplots(figsize=(9, 6))

# 有限の max/30y 倍率を持つ市町
finite = plot_df[plot_df["max / 30y"].apply(lambda v: v != float("inf"))]
ax.scatter(finite["想定最大 km²"], finite["max / 30y"],
           c=finite["沿岸"].map({{True: "#cf222e", False: "#0969da"}}),
           edgecolor="#333", s=80, alpha=0.85)

# 30y=0 (max のみ指定) の市町は ▲ で y=50 にプロット
infs = plot_df[plot_df["max / 30y"].apply(lambda v: v == float("inf"))]
ax.scatter(infs["想定最大 km²"], [50]*len(infs),
           marker="^", s=120,
           c=infs["沿岸"].map({{True: "#cf222e", False: "#0969da"}}),
           edgecolor="#333")

ax.set_yscale("log")
ax.axhline(y=1, color="#aaa", linestyle="--")  # 倍率1 = 拡大なし

結果の図

図9 を選んだ理由: 2 次元の関係 (絶対量 + 拡大倍率) を 1 図で見たいから散布図。 log scale は倍率が市町間で 10〜100 倍も違うため必須。 カテゴリ (沿岸/内陸/盲点)はマーカー色と形で示す。

図9: 想定最大 vs 規模拡大倍率
図9: 想定最大 vs 規模拡大倍率

図9 から読み取れること:

仮説検証と考察

6 仮説の検証結果

仮説 想定 実測 判定
H1 規模拡大 max は ise の 5 倍以上 / 30y の 7 倍以上 max/ise = 5.39, max/30y = 8.01 強支持
H2 深ランクシフト 30y 最多 = rank01 (浅), max 最多 = rank>=04 (深 3m 以上) 30y 最多 = rank01 (0〜0.5 m), max 最多 = rank05 (5.0〜10.0 m) 強支持
H3 カバレッジ拡大 max のみで指定される市町が複数存在 (= 30y 未指定だが max で指定) 30y = 15 市町, max = 20 市町, max のみ追加 = 5 市町 強支持
H4 福山港の優位 (max シナリオ) max シナリオで福山市が 1 位かつ 2 位の倍以上 max 1 位 = 福山市 (56.5 km²), 2 位 = 呉市 (28.9 km²), 倍率 = 1.95 支持
H5 家屋倒壊ゾーン max のみが rank=07 (家屋倒壊等氾濫想定区域) を持つ 30y rk7 = 0, isewan rk7 = 0, max rk7 = 0.006 km² 強支持
H6 告示更新の意味 max のみが多段階深ランク (>5 種) かつ広域 rank 種数: 30y=4, ise=5, max=7; max 告示=2021-08, 他=2017-04 (4 年差) 強支持

主要発見の整理

3 dataset 相互関係の構造発見

本記事の最重要発見は、3 dataset が「同じ高潮現象の異なる規模シナリオ」 ではなく、「異なる時代の異なる想定哲学」を反映している点である。

この 3 段階は頻度 → 過去 → 物理上限という想定の階段であり、 水防法 H27 改正が「過去ベースを超えて物理上限を考えよ」という思想転換を 要請した結果、max のみが質的に異なるデータセットになっている。 3 件を統合分析することで、「告示制度の進化と高潮リスク認識の進化」が 1 つのデータシリーズに刻まれていることが量的に可視化された。

本研究の限界

発展課題

本記事の結果から論理的に導かれる新仮説と、それを検証する具体的課題:

課題 1: 高潮 × 河川 × 津波 「3 機構ハザード重ね」

課題 2: 沿岸島嶼の盲点エリアの社会基盤調査

課題 3: 浸水深 × 標高 (L40) のヒプソメトリック検証

課題 4: 1959 伊勢湾台風の実観測との比較

課題 5: 高潮 × 海面上昇 (気候変動) シナリオの予測