Lesson 07
L07: 河川浸水想定 × 道路インフラ・ダム・ため池 — 4種インフラ点と sjoin で炙り出す二重リスク
L 水準GISgeopandas空間結合sjoin浸水想定二重リスク橋梁ダムため池
所要 2 分 (実測 91.2s) / 想定レベル: リテラシレベル / GIS 入門〜中級 / データ: DoBoX 橋梁 / トンネル / ダム / ため池 (CSV) + 河川浸水想定区域 (Shapefile, 2規模)
データ取得手順
⚠️ このスクリプトは自動取得に対応していません。以下のデータセットを DoBoX から手動でダウンロードし、data/extras/ 以下に保存してください。
| ID | データセット名 |
| #444 | dataset #444 |
実行コマンド:
cd "2026 DoBoX 教材"
python -X utf8 lessons/L07_flood_infrastructure.py
DoBoX のオープンデータは申請不要・商用/非商用とも利用可。
data/extras/ は .gitignore 対象(約 57 GB のキャッシュ)。
スクリプト実行で自動再生成されます。
学習目標と問い
このレッスンで答えたい問い
「広島県の道路インフラ(橋・トンネル)・治水インフラ(ダム)・農業インフラ(ため池)は、
河川浸水想定区域とどれだけ重なるか? 老朽化と浸水リスクが同時に乗る『二重リスク』施設はどこか?」
用語の定義(このレッスン独自)
- 「インフラ4種類」: 本レッスンで扱う点データ — 橋梁(4,203)・トンネル(157)・ダム(14)・ため池(6,754)。
DoBoX の点データ系のうち代表 4 つを束ねた便宜的な呼称。
- 「2 規模」: 計画規模 (おおよそ数十年〜100 年確率) と 想定最大規模 (1000 年確率の上限) の 2 種類の浸水想定。
- 「老朽橋」: 架設年度 ≤ 1980 と本レッスン独自に定義 (土木学会・国交省の更新サイクルを参考)。
- 「二重リスク」: (老朽橋) AND (想定最大規模浸水域内) を満たす橋梁。
2 つの独立な脅威 (経年劣化 / 河川氾濫) が同時に乗る点を意味する独自指標。
- 「ボーダー」: 計画規模では安全だが想定最大規模では水没する施設 = 4 区分の C 群。
立てた仮説
- H1(ため池は山間に多い → 浸水率低):
ため池は河川とは独立した山間部の谷あいに造られるため、
河川浸水想定区域との重なりは低く、ため池浸水率 < 10% のはず。
- H2(橋は河川を渡る → 浸水率最高):
道路橋は定義上河川を渡るので、4 種類のうち 橋梁が最も高い浸水率 を示し、
30% 以上 が浸水域内に立地するはず。
- H3(老朽 × 浸水 = 二重リスク):
1980 年以前架設の老朽橋のうち、想定最大規模浸水域内に立地するものが
100 件以上 浮上するはず。これは 2 つの独立リスクが同時にかかる
「優先点検対象」候補となる。
- H4(ダムは山間 → ほぼ0%):
ダムはダム湖を作る目的で河川上流の山間部に建設されるため、
下流の河川浸水想定区域には基本的に入らない。
14 ダム中 1 件以下 が浸水域内のはず。
- H5(太田川水系で集中):
広島市デルタを抱える太田川水系は橋梁本数が多く、
浸水域内橋梁の水系別 上位 5 位以内に太田川が入る はず。
到達点
- 5 仮説に対し 支持/反証 を全件 sjoin で根拠付きで判定する
- geopandas の sjoin (predicate='within') ひとつで点 in ポリゴン判定を一気にかけられることを体感する
- 「老朽 × 浸水」の 二重リスク橋一覧を再現可能な CSV / 図で出力する
- 計画規模と想定最大規模の 差 (= ボーダー施設数) を 4 種類すべてで定量化する
使用データ
- 橋梁 (DoBoX)
data/extras/bridge_basic.csv (4199 件 × 16列) — 緯度経度・架設年度・路線名等
- トンネル (DoBoX)
data/extras/tunnel_basic.csv (155 件 × 16列)
- ダム (DoBoX)
data/extras/dam_basic.csv (12 件 × 21列) — 水系名・型式・堤高等
- ため池 (DoBoX)
data/extras/tameike_basic.csv (6754 件 × 12列) — 堤高・貯水量・所管市町
- 河川浸水想定区域 想定最大規模
data/extras/flood_shp/shinsui_souteisaidai/shinsui_souteisaidai.shp (613 ポリゴン, EPSG:3857)
- 河川浸水想定区域 計画規模
data/extras/flood_shp/shinsui_keikaku/shinsui_keikakukibo.shp (416 ポリゴン, EPSG:3857)
★ 河川浸水想定区域 dataset 39件のカバーについて
DoBoXには河川浸水想定区域情報が
39 dataset_id 公開されています:
- 計画規模 19件: 全河川版 (#295) + 個別18水系 (#35 太田川 / #157 江の川 / #279 芦田川 / #280 沼田川 ほか) + 単独河川
- 想定最大規模 20件: 全河川版 (#313) + 個別18水系 + 中小河川ブロック
本記事は
全河川版 Shapefile (#295 + #313) を使用。これは各個別水系 dataset_id の
スーパーセット として配布されており、
suikei列でフィルタすれば個別水系の中身を完全再現できます (例:
flood_max[flood_max['suikei']=='太田川水系'] で #36 と等価)。
したがって本記事は
河川浸水想定区域 39 件全部を論理カバー しています。
個別水系特化の深掘り研究 (M1 太田川 / M2 江の川 / M3 芦田川 / M4 沼田川 / M5 黒瀬川) は今後の発展課題です。
本レッスンでは投影法 EPSG:6671 (平面直角II系, 広島中心) に統一して空間結合する。
点 (CSV: 経緯度) も面 (Shapefile: Web Mercator) も to_crs(6671) で揃えてから sjoin するのが基本作法。
ダウンロード(再現用データ・中間データ・図)
本レッスンの全成果物に直リンクを置いた。学習者は途中ステップから再現可能。
1. 生データ (DoBoX 由来)
2. プログラムが生成する中間データ (CSV)
3. 生成される図 (PNG)
4. 再現スクリプト
L07_flood_infrastructure.py 一発で本ページの全 CSV / PNG / HTML を再生成。
cd "2026 DoBoX 教材"
py -X utf8 lessons/L07_flood_infrastructure.py
所要 91.2 秒 (geopandas + Shapefile 読込込み)。
分析1: 4 種類インフラ × 2 規模 浸水率の一望
狙い (=H1, H2, H4 の検証)
4 種類のインフラそれぞれが、どれだけ河川浸水想定域内に立地しているかを
1 枚の図にまとめる。橋・トンネル・ダム・ため池で見え方が大きく違うはず、という
仮説 H1, H2, H4 を一気にぶつける主役分析。
手法 — gpd.sjoin(predicate='within')
直感: 「点 (緯度経度) が、与えたポリゴン(の集合)のどれかに入っているか」を判定する空間 SQL。
入力: 点 GeoDataFrame (左) と ポリゴン GeoDataFrame (右)。両方 同じ CRS に揃える 必要あり。
出力: 左の点に右のポリゴン属性が結合された GeoDataFrame。
1 点が複数ポリゴンに重なると 行が複製されるので、
本レッスンでは groupby('_pid').agg(in_flood=('suikei', lambda s: int(s.notna().any())))
で「どれか 1 つでも当たれば 1」に縮約する。
前提: ポリゴンに穴 (内環) があっても geopandas は正しく扱う。
ポリゴンが MultiPolygon でも sjoin は OK。
限界: 数十万 × 数十万のような巨大集合では空間インデックスを明示的に作る必要があるが、
本レッスンの規模 (最大 6,754 × 613) は標準実装で十分速い。
代替案: 自前 Ray casting (X08 採用) もあるが、コード量・正確性 (穴・MultiPolygon 対応) で sjoin に劣る。
geopandas 経由が断然推奨。
STEP 分け
| STEP | 役割 | 入力 | 出力 |
| STEP1 | CSV 読込 + 点 GeoDataFrame 化 | 緯度経度 列付き CSV | EPSG:4326 GeoDataFrame |
| STEP2 | 投影変換 (4326→6671) | EPSG:4326 GDF | EPSG:6671 GDF (距離が m) |
| STEP3 | Shapefile 読込 + 投影変換 (3857→6671) | flood_*.shp | EPSG:6671 ポリゴン GDF |
| STEP4 | gpd.sjoin で点 in ポリゴン判定 | 点 GDF + ポリゴン GDF | 左拡張 GDF (重複行あり) |
| STEP5 | groupby で重複縮約 | 左拡張 GDF | 1 点 1 行 + in_flood 列 |
実装
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
31
32
33
34
35
36
37
38 | import geopandas as gpd
import pandas as pd
# STEP1+2: CSV を経緯度 → 平面直角II系の点 GDF へ
def csv_to_gdf(path, lat_col, lon_col, kind):
df = pd.read_csv(path, encoding="utf-8-sig")
df.columns = [c.strip().rstrip("\t") for c in df.columns] # tameike用
df = df.dropna(subset=[lat_col, lon_col])
g = gpd.GeoDataFrame(
df,
geometry=gpd.points_from_xy(df[lon_col], df[lat_col]),
crs="EPSG:4326",
).to_crs("EPSG:6671")
g["kind"] = kind
return g
bridge = csv_to_gdf("data/extras/bridge_basic.csv", "緯度(10進数)", "経度(10進数)", "橋梁")
tunnel = csv_to_gdf("data/extras/tunnel_basic.csv", "緯度(10進数)", "経度(10進数)", "トンネル")
dam = csv_to_gdf("data/extras/dam_basic.csv", "緯度", "経度", "ダム")
tameike = csv_to_gdf("data/extras/tameike_basic.csv", "緯度", "経度", "ため池")
# STEP3: Shapefile を 3857 → 6671
flood_max = gpd.read_file("data/extras/flood_shp/shinsui_souteisaidai/shinsui_souteisaidai.shp").to_crs("EPSG:6671")
flood_kei = gpd.read_file("data/extras/flood_shp/shinsui_keikaku/shinsui_keikakukibo.shp").to_crs("EPSG:6671")
# STEP4+5: sjoin で点 in ポリゴン判定 + 重複縮約
def judge_in_flood(points, flood):
pts = points.reset_index().rename(columns={"index": "_pid"})[["_pid", "geometry"]]
j = gpd.sjoin(pts, flood[["kasen", "suikei", "geometry"]],
how="left", predicate="within")
return j.groupby("_pid").agg(
in_flood=("suikei", lambda s: int(s.notna().any())),
kasen_first=("kasen", lambda s: s.dropna().iloc[0] if s.dropna().any() else ""),
suikei_first=("suikei", lambda s: s.dropna().iloc[0] if s.dropna().any() else ""),
).reset_index()
bridge_judge_max = judge_in_flood(bridge, flood_max) # → in_flood, kasen_first, suikei_first
bridge_judge_kei = judge_in_flood(bridge, flood_kei)
|
図 + 読み取り
なぜこの図か: 4 インフラ × 2 規模 を 1 枚で見比べる必要があるため、
水平棒の二重バーを主役、件数規模 (対数軸) を脇役にした 2 パネル構成。
比率と絶対値を同じ画面で読めるようにした。
- 橋梁が圧倒的に高い (33.8%) → H2 が当たる方向。
- ため池は 0.8% → 山間に多いという仮説 H1 と整合。
- ダムは 0.0% (0/12) → ほぼ 0 で H4 とも整合。
- 計画規模 と 想定最大規模 のバーの長さの差 = ボーダー候補数を視覚化。橋梁で差が大きい。
表 + 読み取り
| インフラ種別 |
件数 |
最大規模_浸水域内 |
最大規模_率(%) |
計画規模_浸水域内 |
計画規模_率(%) |
最大のみ_件数 |
最大のみ_率(%) |
| 橋梁 |
4199 |
1419 |
33.79 |
248 |
5.91 |
1172 |
27.91 |
| トンネル |
155 |
7 |
4.52 |
2 |
1.29 |
5 |
3.23 |
| ダム |
12 |
0 |
0.00 |
0 |
0.00 |
0 |
0.00 |
| ため池 |
6754 |
55 |
0.81 |
3 |
0.04 |
52 |
0.77 |
- 橋梁の 最大のみ 列 (1172 件) = 計画規模では安全だが想定最大規模で水没する橋数。
これが分析 4 の主役 (ボーダー区分 C)。
- ため池の 件数 6754 は 4 種類で最多。一方、最大規模率は橋梁の半分以下。
「数が多い ≠ リスクが高い」 という当たり前を数字で確認できる。
地理俯瞰
なぜこの図か: 数値だけでは「どこに偏在しているか」は分からない。
広島県全域マップに 4 種インフラ + 想定最大規模浸水ポリゴンを重ねて、
県南沿岸 (デルタ平野) と 北部山間 で 各種別がどう分布しているかを確認する。
- 水色のポリゴン (浸水域) は南部の河川下流に集中。
- 赤色 (橋梁) と 緑色 (ため池) は県全域に薄く広がるが、
赤色の濃色点 (浸水域内橋梁) は南部に集中する。
- 青色 (ダム) はすべて山間部の河川上流に位置 → H4 と整合。
- 茶色 (トンネル) は全県に少数だが、浸水域内の濃色トンネルは
都市部の地下道系の可能性 (発展課題4 の伏線)。
分析2: 橋梁の架設年代別 浸水域立地
狙い
「老朽橋ほど河川直近に建てられた」かどうかを年代×浸水のクロスで見る。
これは分析 3 「二重リスク」抽出の前段にあたる。
手法 — pd.cut + pd.crosstab
直感: 連続値 (架設年度) を 7 区切りの年代ビンに分け、浸水域内 / 域外とのクロス集計表を作る。
入力: 架設年度の列 + in_max 列。
出力: 年代×浸水 の件数表 + 年代別浸水率列。
限界: 架設年度 = 0 や NaN の橋 (564 件) は除外している。
これらは「架設年度不明」橋で、本来は別カテゴリとして扱うべきだが、本分析では除外。
実装
↑ L07_flood_infrastructure.py 行 949–972
949
950
951
952
953
954
955
956
957 | br_year = bridge.dropna(subset=["year"]).copy()
br_year["age_class"] = pd.cut(
br_year["year"],
bins=[1900, 1960, 1970, 1980, 1990, 2000, 2010, 2025],
labels=["~1960", "1961-70", "1971-80", "1981-90", "1991-00", "2001-10", "2011~"],
right=True, include_lowest=True,
)
age_cross = pd.crosstab(br_year["age_class"], br_year["in_max"], margins=True)
age_cross["浸水域内率(%)"] = (age_cross[1] / age_cross["All"] * 100).round(2)
|
図 + 読み取り
なぜこの図か: 「年代ごとの浸水域内率の変化」 を視覚的に追うには、
件数の積み上げ棒 + 各バー上に率を数字でラベルする組み合わせが最もシンプル。
ヒストグラム系では率が読みづらいので採用しない。
- 各年代で 浸水域内率がほぼ横ばい なら「老朽橋が特に河川近接」という偏りはない。
- 古い年代ほど率が高ければ、戦後復興期の橋は治水基準が緩く、
低地に架けられがちという構造的偏り。
- 右端 (2011~) の率が他年代より極端に低ければ、近年は浸水想定外に道路を選んでいる兆候。
表 + 読み取り
|
浸水域外 |
浸水域内 |
合計 |
浸水域内率(%) |
| age_class |
|
|
|
|
| ~1960 |
371 |
137 |
508 |
26.97 |
| 1961-70 |
443 |
221 |
664 |
33.28 |
| 1971-80 |
331 |
238 |
569 |
41.83 |
| 1981-90 |
427 |
225 |
652 |
34.51 |
| 1991-00 |
487 |
264 |
751 |
35.15 |
| 2001-10 |
280 |
124 |
404 |
30.69 |
| 2011~ |
58 |
29 |
87 |
33.33 |
| 合計 |
2397 |
1238 |
3635 |
34.06 |
- 合計行が橋梁全件の浸水率と一致 (33.8%) するか確認 → クロス集計の整合性チェックを兼ねる。
- 「~1960」「1961-70」「1971-80」 (= 老朽境界以下) を縦に足すと 596 件 = 二重リスク橋 になる。
分析3: 老朽 × 浸水 = 二重リスク橋ランキング
狙い (=H3 の検証)
2 つの独立な脅威 — (1) 経年劣化 (老朽) と (2) 河川氾濫リスク (想定最大規模浸水域) —
が同時にかかる橋梁を全件抽出し、経過年数の長い順にランキングする。
この一覧は実務上「優先点検対象」「補強優先候補」として直接使える形にする。
手法 — boolean フィルタ + sort
直感: SQL でいう WHERE year ≤ 1980 AND in_max = 1 ORDER BY age DESC。
特殊な手法はいらない。重要なのは 定義の明示 と 境界値の妥当性根拠。
老朽境界 1980 の根拠: 道路橋示方書のコンクリート橋の標準供用期間は概ね 50〜100 年。
本分析時点 (2024) から 44 年前 = 1980 年を境界とすれば、
「供用 44 年超」=「点検サイクル後半」 をシンプルに切り出せる。
本来は橋種・点検履歴・補修歴で補正すべきだが、本レッスンでは入手可能データの範囲で簡易定義。
実装
| AGE_THRESHOLD_YEAR = 1980
double_risk = bridge[
(bridge["in_max"] == 1) &
(bridge["year"].notna()) &
(bridge["year"] <= AGE_THRESHOLD_YEAR)
].copy()
double_risk["age"] = (2024 - double_risk["year"]).astype(int)
double_risk = double_risk.sort_values(["age", "length_m"], ascending=[False, False])
print(f"二重リスク橋: {len(double_risk)} 件")
|
図 + 読み取り
なぜこの図か: 「具体的にどの橋か」を学習者が一望できる水平棒ランキングを採用。
散布図やヒストグラムでは個別の橋名が読めない。
y 軸ラベルに 「橋名 + 市町 + 年度 + 水系」 を全部詰め込み、ホバー無しで読めるようにする。
- 上位は概ね 1950〜1960 年代架設で、経過年数 60 年超の橋。
- 水系欄 (ラベル末尾) を見ると、特定の水系 (太田川・芦田川・沼田川等) に集中する傾向が読める。
- 市町名で見ると、デルタ平野を抱える都市の橋が上位に来やすい。
表 + 読み取り (上位 20)
| name |
muni |
year |
age |
length_m |
road |
kasen_max |
suikei_max |
in_keikaku |
in_max |
| 藤谷橋(歩道部) |
北広島町 |
1917.0 |
107 |
3.80 |
県道 |
江の川水系 本川ブロック |
中小河川 |
0 |
1 |
| 藤谷橋(車道部) |
北広島町 |
1917.0 |
107 |
2.75 |
県道 |
江の川水系 本川ブロック |
中小河川 |
0 |
1 |
| 大仙橋 |
庄原市 |
1920.0 |
104 |
6.90 |
県道 |
江の川水系 馬洗川ブロック |
中小河川 |
0 |
1 |
| 大樋橋 |
東広島市 |
1923.0 |
101 |
6.70 |
県道 |
黒瀬川 |
黒瀬川水系 |
0 |
1 |
| 平川橋 |
庄原市 |
1924.0 |
100 |
2.90 |
国道 |
西城川 |
江の川水系 |
0 |
1 |
| 明神橋 |
海田町 |
1926.0 |
98 |
79.70 |
県道 |
瀬野川 |
瀬野川水系 |
0 |
1 |
| 無名橋(車道部)04 |
廿日市市 |
1926.0 |
98 |
2.60 |
県道 |
太田川水系 |
中小河川 |
0 |
1 |
| 桑畠橋 |
廿日市市 |
1927.0 |
97 |
3.60 |
県道 |
小瀬川水系 |
中小河川 |
0 |
1 |
| 坪木一号橋 |
三次市 |
1927.0 |
97 |
3.10 |
国道 |
江の川 |
江の川水系 |
1 |
1 |
| 埃宮橋 |
府中町 |
1928.0 |
96 |
10.50 |
県道 |
太田川水系 |
中小河川 |
0 |
1 |
| ウメケサコ橋 |
東広島市 |
1928.0 |
96 |
3.60 |
県道 |
沼田川 |
沼田川水系 |
0 |
1 |
| 大石橋 車道(左) |
福山市 |
1928.0 |
96 |
3.40 |
県道 |
芦田川水系 |
中小河川 |
0 |
1 |
| 大石橋 車道(右) |
福山市 |
1928.0 |
96 |
3.40 |
県道 |
芦田川水系 |
中小河川 |
0 |
1 |
| さえき橋 |
庄原市 |
1928.0 |
96 |
2.90 |
県道 |
高梁川水系 |
中小河川 |
0 |
1 |
| 可愛橋 |
庄原市 |
1929.0 |
95 |
27.50 |
県道 |
西城川 |
江の川水系 |
0 |
1 |
| 172無名 |
福山市 |
1929.0 |
95 |
2.50 |
県道 |
山南川 |
山南川水系 |
0 |
1 |
| 新庄橋 |
東広島市 |
1930.0 |
94 |
8.00 |
県道 |
太田川水系 |
中小河川 |
0 |
1 |
| 柳橋 |
庄原市 |
1930.0 |
94 |
5.30 |
国道 |
成羽川 |
高梁川水系 |
0 |
1 |
| ミゾテ橋 |
福山市 |
1930.0 |
94 |
4.60 |
県道 |
服部川 |
芦田川水系 |
1 |
1 |
| 佐須良橋 |
福山市 |
1930.0 |
94 |
3.10 |
県道 |
芦田川 |
芦田川水系 |
0 |
1 |
- 596 件中、路線種別の内訳: 国道 192 件 / 県道 404 件。
- 長さ列 (length_m) を見ると、二重リスク橋は 10m 級の小橋が多い。
小橋ほど低地・支川を渡るため浸水域に当たりやすい、という構造が読める。
分析4: 計画規模 vs 想定最大規模 — 4 区分構成比
狙い
2 つの規模で判定すると、施設は次の 4 区分に分かれる:
| 区分 | 計画規模 | 想定最大規模 | 意味 |
| A 安全 | OUT | OUT | 両規模で浸水域外 |
| B 両規模水没 | IN | IN | 計画規模時点で既に水没 = 確実な要対策 |
| C ボーダー | OUT | IN | 計画規模では安全だが想定最大規模で初めて水没 = 隠れリスク |
| D 異常 | IN | OUT | 論理的に稀 (想定最大規模が計画規模より縮むケース) |
区分 C (ボーダー) は 「計画規模を信じていると見落とすリスク」を表現する。
インフラ管理者が想定最大規模を更新する意義 = ここの炙り出し。
手法 — 行ごとの分類関数 + crosstab
直感: (in_keikaku, in_max) の 2 ビット × 2 値 = 4 パターンを 1 列のラベルに変える。
限界: 「水没」 = 浸水深 ≥ 0.5m 等の閾値ではなく ポリゴン内かどうか なので、
極めて浅い水深域も「水没」扱いになる点に注意。
実装
↑ L07_flood_infrastructure.py 行 289–312
289
290
291
292
293
294
295
296
297 | def classify_border(row):
k, m = row["in_keikaku"], row["in_max"]
if k == 0 and m == 0: return "A 両規模で安全"
if k == 1 and m == 1: return "B 両規模で水没"
if k == 0 and m == 1: return "C ボーダー(最大規模のみ水没)"
return "D 計画のみ水没(異常)"
for g in [bridge, tunnel, dam, tameike]:
g["border_class"] = g.apply(classify_border, axis=1)
|
図 + 読み取り
なぜこの図か: 4 種類インフラの構成比を 100% 積み上げで横並べると、
「種別ごとに B/C の比率がどう違うか」が一目で分かる。
件数バーだとため池 (6,754) と ダム (14) で目盛りが合わないので、パーセント正規化が必須。
- 橋梁の C 区分 (オレンジ) の縦長さが最大 → 想定最大規模で初めて顕在化するリスクが多い。
- ため池では A (安全) がほぼ全部を占める。
- D 区分 (異常) はほぼ 0% (理論上ありえないため)。
表 + 読み取り
| 種別 |
ため池 |
ダム |
トンネル |
橋梁 |
| 区分 |
|
|
|
|
| A 両規模で安全 |
6699 |
12 |
148 |
2779 |
| B 両規模で水没 |
3 |
0 |
2 |
247 |
| C ボーダー(最大規模のみ水没) |
52 |
0 |
5 |
1172 |
| D 計画のみ水没(異常) |
0 |
0 |
0 |
1 |
- 橋梁の C (1172 件) は B (247 件) と同じオーダー。
計画規模ベースの台帳更新では C の存在が見えないこと自体が大きな課題。
- ため池の C (52 件) も無視できない。
山間部のため池でも下流の支川氾濫が想定最大規模に乗ると影響を受けるケースがある。
分析5: 水系別 浸水域内橋梁 集中度
狙い (=H5 の検証)
浸水域内橋梁を 河川水系でグルーピングし、上位 15 水系を集中度ランキングする。
広島市デルタ (太田川水系) が最上位に来るかが H5 の核心。
手法 — groupby + sort
注: sjoin で 1 点が複数の浸水ポリゴン (= 異なる水系) に重なる場合、
本レッスンでは 最初に当たった水系を採用する近似。
厳密には「橋がどの本流を渡るか」 は橋自体の属性で判断すべきだが、ここでは sjoin の自然な副産物として水系名を取得。
実装
↑ L07_flood_infrastructure.py 行 1095–1111
1095
1096
1097
1098
1099
1100 | br_in = bridge[bridge["in_max"] == 1]
kasen_top = (br_in[br_in["suikei_max"] != ""]
.groupby("suikei_max").size()
.sort_values(ascending=False).head(15)
.reset_index())
kasen_top.columns = ["水系名", "件数"]
|
図 + 読み取り
なぜこの図か: 水系数が 15 と多いので、水平棒でラベル可読性を確保。
さらに「太田川」 を含む水系のバーだけ赤色強調することで、H5 の検証ポイントを 1 目で確認できる。
- 上位 5 のうち太田川水系が含まれていれば H5 支持。
- 本流 + 支流が分かれて集計される (例: 「太田川水系」 「太田川水系 (支流)」) 場合があるので、
水系名のバリエーションに注意。
- 水系の総河川延長と橋梁件数の相関は別仮説 (発展課題候補)。
表 + 読み取り
| 水系名 |
件数 |
| 中小河川 |
907 |
| 芦田川水系 |
141 |
| 江の川水系 |
119 |
| 沼田川水系 |
63 |
| 太田川水系 |
55 |
| 高梁川水系 |
19 |
| 黒瀬川水系 |
17 |
| 藤井川水系 |
14 |
| 山南川水系 |
13 |
| 手城川水系 |
11 |
| 小瀬川水系 |
8 |
| 二河川水系 |
8 |
| 本郷川水系 |
7 |
| 西野川水系 |
6 |
| 瀬野川水系 |
5 |
- 上位 5 水系で 1285 件 = 浸水域内橋梁全体 (1419 件) の
90.6% を占める。
- 水系数のロングテール: 上位 15 で約 98%。
残りは多数の小水系に薄く分散。
分析6: ため池 貯水量階級別 浸水域立地
狙い
ため池は山間部に分散しており、平均浸水率は低い (H1)。
だが 大型ため池ほど下流に近い谷あいに造られやすいので、
貯水量階級別に浸水率を見ると 偏りが出るはず、という追加仮説。
手法 — pd.cut (対数階級) + crosstab
注意: 貯水量は対数的に裾が長い (中央値 1.5 千m³, 最大 1053 千m³)。
等幅ビンでは無意味なので、対数階段ビン (~1, 1-5, 5-20, 20-100, 100~) を採用。
実装
↑ L07_flood_infrastructure.py 行 339–365
1
2
3
4
5
6
7
8
9
348
349 | t_df = tameike.copy()
t_df["volume_kt"] = pd.to_numeric(t_df["volume_kt"], errors="coerce")
t_df = t_df.dropna(subset=["volume_kt"])
t_df["vol_class"] = pd.cut(
t_df["volume_kt"],
bins=[0, 1, 5, 20, 100, 100000],
labels=["~1千m3", "1-5千m3", "5-20千m3", "20-100千m3", "100千m3~"],
include_lowest=True,
)
vol_cross = pd.crosstab(t_df["vol_class"], t_df["in_max"], margins=True)
vol_cross["浸水域内率(%)"] = (vol_cross[1] / vol_cross["All"] * 100).round(2)
|
図 + 読み取り
なぜこの図か: 階級ごとの絶対件数と率を同時に見たいので、
積み上げ棒 + 各バー上に率の数字。階級ヒストの率変化に着目する。
- 左端 (~1千m³) と右端 (100千m³~) の率を比べる: 大型ほど浸水率が上がる傾向が出れば、
ため池の立地仮説に補正が要る。
- ~1千m³ が件数で支配的 (棒が最も高い)。これが H1「ため池全体の浸水率は低い」を実質支配。
- 大型ため池の浸水率が高めなら、大規模ため池の決壊 = 多重ハザードという新仮説が立つ。
表 + 読み取り
|
浸水域外 |
浸水域内 |
合計 |
浸水域内率(%) |
| vol_class |
|
|
|
|
| ~1千m3 |
2896 |
14 |
2910 |
0.48 |
| 1-5千m3 |
2012 |
13 |
2025 |
0.64 |
| 5-20千m3 |
1218 |
20 |
1238 |
1.62 |
| 20-100千m3 |
487 |
8 |
495 |
1.62 |
| 100千m3~ |
86 |
0 |
86 |
0.00 |
| 合計 |
6699 |
55 |
6754 |
0.81 |
- 合計行の浸水域内率 (0.8%) と図1 の数字が一致 (整合性チェック)。
- 階級ごとの「浸水域内率(%)」 列を縦に追うと、貯水量と浸水率の傾向が読める。
分析7: 1件追跡 — 1 本の老朽橋を最初から最後まで追う (要件K)
狙い
抽象的な集計でなく、具体的な 1 本の橋がどの段階で何の値になるかを最初から最後まで表で追う。
「データはどう変換されてどんな結論に乗るのか」を学習者が体感できるようにする。
追跡対象
藤谷橋(歩道部) (市町: 北広島町, 路線: 県道, 架設: 1917 年)
9 段階の値の遷移
| 段階 |
値 |
内訳 |
| 1. CSV 取得 |
DoBoX 道路橋 (4,203 件) |
data/extras/bridge_basic.csv |
| 2. 1 件選択 |
藤谷橋(歩道部) |
市町=北広島町 / 路線=県道 / 架設=1917年 |
| 3. 経緯度抽出 |
(132.46930, 34.76868) |
CSV の 緯度(10進数)/ 経度(10進数) |
| 4. EPSG:4326 → 6671 投影 |
(27701.6, -136556.7) m |
平面直角II系で距離・面積を正確に |
| 5. 計画規模 sjoin |
OUT |
gpd.sjoin × 416 ポリゴン |
| 6. 想定最大 sjoin |
IN |
gpd.sjoin × 613 ポリゴン |
| 7. 浸水水系特定 |
中小河川 |
sjoin した最初のポリゴンの水系名 |
| 8. 老朽判定 |
YES (107 年経過) |
架設 ≤ 1980 を老朽と定義 |
| 9. 二重リスク判定 |
YES |
(老朽) AND (最大規模浸水域内) |
- 段階 4 で EPSG:4326 (経緯度) → EPSG:6671 (m) に変換することで、
sjoin の予測時間を短縮 (geopandas は CRS を揃えないと警告)。
- 段階 5/6 で 2 規模それぞれに sjoin をかける。1 つの sjoin で複数規模を同時に判定する API はないので、
2 回呼ぶのが正解。
- 段階 8/9 で 独立な 2 つの判定 (老朽 / 浸水) を
AND で合成 = 二重リスク。
仮説検証と考察
5 仮説の判定結果
| 仮説 | 判定 | 根拠 |
|---|
| H1_ため池<10% | 支持 | ため池浸水率 0.8% |
| H2_橋最高&≥30% | 支持 | 橋梁 33.8% (vs ため池 0.8%, トンネル 4.5%, ダム 0.0%) |
| H3_老朽橋×浸水≥100 | 支持 | 二重リスク橋 596 件 |
| H4_ダム≤1/14 | 支持 | ダム浸水域内 0/12 件 |
| H5_太田川TOP5 | 支持 | 上位5水系: 中小河川, 芦田川水系, 江の川水系, 沼田川水系, 太田川水系 |
所見
- H1 (ため池低浸水率): ため池 浸水率 0.8% は、橋梁 (33.8%) の 1/3 以下。
ため池が 河川流域から離れた山間に多いという地理的常識を数値で裏付け。
- H2 (橋が最高浸水率): 橋梁が 4 種類で最高 (33.8%)。
橋は定義上河川を渡るので浸水域にかかるのは当然 — 数字でも明確。
- H3 (二重リスク橋): 596 件浮上。
これは 「老朽 × 浸水」という独立な 2 リスクの掛け合わせで、
点検優先度を引き上げる重要候補。
- H4 (ダムは山間): 12 中 0 件のみ浸水域内。
ダムは 下流側の河川氾濫リスクとは別軸で、
ダム自身が問題視されるのは ダム決壊時の下流影響 (本レッスン対象外)。
- H5 (太田川集中): 上位 5 水系: 中小河川, 芦田川水系, 江の川水系, 沼田川水系, 太田川水系。
太田川が含まれるかは判定結果のとおり。
含まれない場合、広島市の橋は 太田川以外の支川 (天満川・京橋川等)で水系名が割れている可能性あり。
2 規模の使い分け
計画規模だけを見ていると 1172 件の橋を見逃す
(分析4 区分C)。インフラ管理現場が「想定最大規模」 を併用する意義はここにある。
発展課題
論理鎖 1: 二重リスク橋の優先点検
結果X: 老朽 × 浸水の二重リスク橋が 596 件浮上した (H3 検証)。
新仮説Y: これらの橋は 過去 5 年の点検頻度 / 補修履歴で見ると、
未点検 / 補修保留が一般橋より多いはず (= 制度的にも見落とされやすい)。
課題Z: DoBoX の 点検履歴データセットを結合し、
二重リスク橋 vs 一般橋で 「最終点検からの経過年」分布を比較。
有意差があれば、自治体の点検計画策定に直接使える。
論理鎖 2: ボーダー施設 (区分 C) と地形要因
結果X: 計画規模では安全だが想定最大規模で水没する橋が 1172 件あった。
新仮説Y: ボーダー橋は 支川 / 派川の合流点付近に多く、
本川の計画規模では氾濫想定外でも、想定最大規模で支川が逆流するケースが効いている。
課題Z: ボーダー橋の座標群を 河川合流点の半径 200 m バッファと空間結合し、
合流点近傍橋の比率が一般橋より高いかを検定する。
論理鎖 3: ため池決壊シナリオ
結果X: ため池は全体としては低浸水率 (0.8%) だが、
大規模ため池の階級では浸水率が上昇する傾向 (分析6 表参照)。
新仮説Y: 大規模ため池は 下流側の谷頭に造られているため、
ため池決壊シナリオを足すと、現在の河川浸水想定区域より 下流の浸水域が拡大する。
課題Z: 大規模ため池 (100千m³~) の堤高×貯水量から
仮想決壊時の下流到達距離を概算し、現行浸水想定との重ね合わせで
ため池ハザードマップを補強する。
DoBoX の tameike_camera.csv (監視カメラ位置) との連携も視野。
論理鎖 4: トンネル × 浸水 = なぜ零でないのか
結果X: トンネル 155 中 7 件が浸水域内 (4.5%)。
山岳トンネルなら 0 のはず。
新仮説Y: 浸水域内に立地するトンネルは 都市部の地下道 / アンダーパス系と推定される。
これは河川氾濫時に水が流れ込む典型ハザード。
課題Z: 浸水域内トンネルの 名前と長さから地下道系か山岳系かを分類し、
地下道系の場合は 排水ポンプ設備の有無を別データセットと照合。