Lesson 06

2024-07-01 豪雨日 — 雨域セルの空間 - 時間進行を読む

v2-rewriteリテラシ時空間空間統計属性結合
所要 120分 / 想定レベル: リテラシ / データ: 2データ結合: #1275 雨量10分値 (resource 94500) + #1279 監視カメラ

データ取得手順

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

IDデータセット名
#222dataset #222
#666dataset #666
#888都市計画区域情報_区域データ_安芸高田市_行政区域
#999dataset #999
#1275観測情報_雨量日集計
#1279県内のカメラ情報

実行コマンド:

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

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

学習目標と問い

このレッスンで答えたい問い

2024-07-01 の豪雨日、雨域は県内をどう動き、どこに集中し、いつピークを迎えたか? 10分間隔の生雨量データだけから、時間と空間の両方で起きていたことを読み解けるか。

用語の定義(このレッスン独自)

  • 「雨域」: ある時刻に雨が比較的強く降っている 地域のかたまり。 本レッスンでは観測所別の雨量を空間的に滑らかに補間 (KDE) して輪郭で表す。
  • 「カーネル密度推定 (KDE)」: 各観測点を中心とした「滑らかな小山」を地図に重ねて、 点群を 連続的な濃淡分布に変換する集計ツール。 本レッスンでは雨量を山の高さの重みに使う(重み付き KDE)。
  • 「重心 (Center of Mass)」: 雨量を「重さ」と見立てた時の つり合いの中心点。 雨が県西部に集中していれば重心も西に寄る。各時刻ごとに 1 点に要約される。
  • 「Moran's I (モランのアイ)」: 「近くの観測所同士で雨量が似ているか」を 1 つの数値で表す指標。+1 に近いほど局所集中、0 で無関係、−1 で交互パターン。
  • 「代理座標」: 雨量観測所には公式の緯経度が公開されていない。 本レッスンでは 同じ河川にあるカメラの平均緯経度を雨量観測所の代わりに使う。 誤差は数 km 〜 十数 km だが、県全体の時空間進行を見るには十分。

立てた仮説

  1. H1(雨域は移動する): 雨域は梅雨前線の進行に従って 数時間で県内を抜けるはず。 重心の移動軌跡(24 個の点を線で結んだ図)として可視化できる
  2. H2(空間クラスタ性は時刻で変動): 強雨時間帯ほど雨は 1〜2 か所に局所集中し (Moran's I が高い)、合間は分散して降るはず
  3. H3(県全体での同時ピーク): 観測所ごとのピーク時刻は 1〜2 の時間帯に モードを持つはず (梅雨前線が県を一斉に通過するため同時多発)
  4. H4(属性結合で座標欠落を代替できる): 雨量観測所には緯経度が無いが、 河川名をキーにカメラと結合すれば、KDE/重心/Moran 計算に十分な代理座標が得られるはず
  5. H5(上位観測所の波形は短時間集中型): 日合計上位 10 観測所は、24 時間に分散ではなく 1〜2 時間にピークが集中する波形を持つはず(局所豪雨 = 短時間に降りきる)

到達点

使用データ

本レッスンは 2 つのデータセットを結合して使う。雨量データには公式座標が無いため、 カメラの座標を 河川名をキーに代用する(仮説 H4 の検証対象)。

なぜ 2024-07-01 か: 2018 年 7 月の西日本豪雨と同じ梅雨末期に当たる時期。 14 日窓(DoBoX #1275 の公開単位)の中で県内日合計が最大級だった日のひとつで、 時空間進行が読みやすい。

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

本レッスンの全成果物に直リンクを置いた。途中ステップから再現したい学習者向け。

1. 生データ(DoBoX 由来)

ファイル形式サイズ取得元
data/rain_2024/rain_2024-07-01.csv CSV (10分値, UTF-8 BOM, 5段ヘッダ)約 1.2 MB DoBoX #1275 resource_id=94500
data/camera_list.csv CSV (緯度・経度・路河川名等)約 70 KB DoBoX #1279

2. プログラムで生成される中間データ(本レッスンの実行成果物)

ファイル内容使う分析
L06_hourly_rainfall.csv 24 時刻 × 約 400 観測所の 1 時間集約雨量分析 1〜5 共通の入力
L06_station_coords.csv 観測所 × (河川/水系/推定 lat/推定 lon/解決ソース)分析 1〜3 の座標源
L06_com_trajectory.csv 24 時刻の重心位置と移動速度 (km/h)分析 2 雨域重心軌跡
L06_moran_hourly.csv 24 時刻の Moran's I と時間総雨量分析 3 空間自己相関
L06_peak_hours.csv 観測所別ピーク時刻 (h)分析 4 ピーク時刻分布
L06_daily_totals.csv 観測所別の日合計雨量 (mm)分析 5 Top10 抽出元
L06_top10_summary.csv 上位 10 観測所のサマリ(水系・河川・日合計・ピーク・集中度)分析 5 表

3. 図 PNG

4. 再現スクリプト

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

スクリプト本体: lessons/L06_july1_heatmap.py。 データが無ければ ensure_dataset() が DoBoX から自動取得。

分析1: 雨域の空間 KDE small multiples (24時間)

狙い

「1 日の中で雨域がどこからどこへ移動したか」を、24 枚の地図を時系列で並べて一望する。 仮説 H1(雨域は移動する)を視覚的に検証するための分析。

用語: 「カーネル密度推定 (KDE)」は、観測点の点群を 滑らかな濃淡分布に変換するツール。 各点を中心とした「小山」を地図に重ねて足し算し、重みつきの地図を作る。 今回は雨量を「山の高さ」の重みに使うので、雨が強い場所ほど山が高い。 24 個の地図を並べる手法を small multiples(小窓並列) と呼ぶ — 時間変化を一目で読める。

このツールで何ができて、何ができないか(要件 J)

項目このツール
入力観測点の (緯度, 経度, 重み) のリスト
出力地図上のグリッド (80×80) 各点の濃度値
主なパラメータ バンド幅 h(小山の幅)。本レッスンは h=0.07°≒ 7 km — 強雨セル 1 つの典型サイズ
限界 (1) h を変えると印象が変わる。h 小 → 点状、h 大 → 全県塗り潰し
(2) 観測点が少ない地域では信頼性が低い (山陰など)
(3) 点と点の間を 滑らかに「埋めている」だけで、本当にそこで雨が降っていたかは保証しない
代替 IDW (逆距離加重)、ボロノイ補間、クリギング — KDE は最も単純で実装しやすい
数式の細部 気にしなくて良い。「滑らかな小山を足し合わせる」イメージで十分

1 日のデータがどう変換されるか(Before/After 表、要件 K)

段階内容サイズ
① 生 CSV (rain_2024-07-01.csv) 10 分間隔の雨量。5 段ヘッダ付き(観測所名/河川名/水系名/事務所名/単位行) 144 行 × 約 400 列
parse_rain_csv() で tidy DatetimeIndex × 観測所列の数値表 (144, 313+)
resample("1h").sum() 1 時間ごとに 6 個の 10 分値を足す (24, 313)
④ 河川名で代理座標を結合 (分析 4 で詳細) 各列に (lat, lon) が付く 列数は変わらず、
各列に座標メタが付与
⑤ 各時刻 h で kde_grid(weights=hourly[h]) 80×80 グリッドの濃度値 (80, 80) × 24 時刻
contourf で等高線塗り → 24 枚の小窓 図 1 の small multiples 6 行 × 4 列 = 24 図

実装(狙いと要点)

狙い: 加重ガウシアンを各観測所に置いてグリッドに足し算するだけのシンプル実装。 要点: w > 0 の観測所だけループに入れて高速化。バンド幅 h = 0.07

L06_july1_heatmap.py 行 700–758

 1
 2
 3
 4
 5
 6
 7
 8
 9
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
def kde_grid(weights, bandwidth=0.07, grid=80):
    """加重 KDE を等間隔グリッド上で評価。
    weights: 各観測所のその時刻の雨量 (mm)
    bandwidth: ガウシアンの「幅」(度)。0.07° ≒ 7 km
    """
    xs = np.linspace(LON_MIN, LON_MAX, grid)
    ys = np.linspace(LAT_MIN, LAT_MAX, grid)
    XX, YY = np.meshgrid(xs, ys)
    Z = np.zeros_like(XX)
    h2 = bandwidth ** 2
    for la, lo, w in zip(lats, lons, weights):
        if w <= 0:
            continue
        # 各観測所を中心とした「滑らかな小山」を足し合わせる
        Z += w * np.exp(-((XX - lo) ** 2 + (YY - la) ** 2) / (2 * h2))
    return XX, YY, Z

# 24 コマを 6 × 4 で並べて時間進化を一望 (small multiples)
fig, axes = plt.subplots(6, 4, figsize=(13, 16), sharex=True, sharey=True)
for h in range(24):
    XX, YY, Z = kde_grid(hourly.iloc[h].values, bandwidth=0.07)
    ax = axes[h // 4, h % 4]
    if Z.max() > 0:
        ax.contourf(XX, YY, Z, levels=12, cmap="Blues")
    ax.scatter(lons, lats, s=3, c="#666", alpha=0.35)  # 観測所点
    total = float(np.nansum(hourly.iloc[h].values))
    ax.set_title(f"{h:02d}:00-{h:02d}:59  Σ={total:.0f}mm", fontsize=9)

結果(図と読み取り)

なぜこの図か: 「雨域がどう移動したか」を見るには、同じ地図枠を時刻順に 24 枚並べるのが最も直感的。 1 枚の動画にすれば滑らかに見えるが、紙面では並列表示が読み取りやすい。 バンド幅 7 km 程度に揃えると、強雨セルが「色のかたまり」として現れる。

図 1: 1 時間ごとの空間 KDE 24 枚。塗り色の濃さが雨量の強さ、灰色点が観測所
図 1: 1 時間ごとの空間 KDE 24 枚。塗り色の濃さが雨量の強さ、灰色点が観測所

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

分析2: 雨域重心 (Center of Mass) の軌跡

狙い

「24 枚の KDE をたった 1 点に要約する」。各時刻の雨量を「重さ」と見なした つり合いの中心を計算し、24 個の点を線で結べば「雨域がどっちへ動いたか」が一目で分かる。 仮説 H1 を 定量化する分析。

用語: 「重心 (Center of Mass)」とは、雨量を質量と見立てた時の つり合いの中心。 雨が県西部に偏っていれば重心も西へ寄り、均等なら県中央に来る。 1 時刻 = 1 個の (緯度, 経度) に要約されるので、24 時刻なら 24 個の点が出る。

このツールで何ができて、何ができないか(要件 J)

項目このツール
入力観測点の座標 (lat, lon) と重み (雨量)
出力1 個の (重心 lat, 重心 lon)
主なパラメータなし(重み付き平均なので素朴)
限界 (1) 雨が 2 か所に分かれている時、重心はその中間に来る — 「実際にどこも降っていない場所」を指してしまう
(2) 外れ値 1 つに引きずられやすい (極端に強雨の 1 地点が重心を引っ張る)
代替 モード位置 (最大雨量観測所)、複数モード抽出 (k-means クラスタ重心)
数式の細部 np.average(coords, weights=rainfall) 一発。気にしなくて良い

1 日のデータがどう変換されるか(Before/After 表、要件 K)

段階内容サイズ
① 1 時間集約データ (分析 1 の ③)24 × 観測所数の雨量(24, 313)
② 各時刻 h で np.average(lons, weights=hourly[h]) その時刻の重心の経度・緯度2 個のスカラー
③ 24 時刻分まとめ(時刻 h, 重心 lon, 重心 lat, 総雨量)24 行 × 4 列
④ 連続時刻の差分 → 移動速度 1 度 ≒ 緯度 111 km / 経度約 91 km @lat34.5 で km/h 換算23 個の差分
⑤ 散布 + 矢印 (図 2 左) と 棒グラフ (図 2 右)軌跡と速度の可視化図 2

実装(狙いと要点)

狙い: 雨量を重みにした座標の加重平均で各時刻 1 点を出す。 要点: 雨量ゼロ時刻は NaN にして矢印を切る。差分 → km 換算で速度化。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
KM_LON = 111.0 * np.cos(np.deg2rad(34.5))   # 経度 1 度 ≒ 91 km @広島緯度
KM_LAT = 111.0                              # 緯度 1 度 ≒ 111 km

com = []
for h in range(24):
    w = np.where(np.isnan(hourly.iloc[h].values), 0, hourly.iloc[h].values)
    if w.sum() > 0:
        # 重み付き平均 = 雨量を「重さ」とした重心
        clon = float(np.average(lons, weights=w))
        clat = float(np.average(lats, weights=w))
    else:
        clon, clat = np.nan, np.nan
    com.append({"hour": h, "lon": clon, "lat": clat, "total": float(w.sum())})

com_df = pd.DataFrame(com)
# 移動速度 (km/h)
dlon = com_df["lon"].diff().values * KM_LON
dlat = com_df["lat"].diff().values * KM_LAT
com_df["speed_kmh"] = np.sqrt(dlon ** 2 + dlat ** 2)

結果(図と読み取り)

なぜこの図か: 雨域の 進行方向と速度を見るには「軌跡(散布 + 矢印)」と 「速度の時刻別棒」を並列表示するのが最も読みやすい。色は時刻 (0→23 h) で、 矢印が連続時刻の移動を示す。

図 2: 雨域重心の軌跡 (左, 色 = 時刻 0→23h) と時刻別移動速度 (右)
図 2: 雨域重心の軌跡 (左, 色 = 時刻 0→23h) と時刻別移動速度 (右)

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

結果(表と読み取り)

表 1: 24 時刻の重心位置と移動速度
時刻 h 重心 経度 重心 緯度 時間雨量計 (mm) 前時刻からの移動 (km/h)
0 132.6691 34.5837 839.5
1 132.5855 34.5633 615.0 7.98
2 132.4469 34.5190 1527.0 13.60
3 132.5335 34.4862 4685.5 8.72
4 132.7764 34.4871 3931.0 22.22
5 132.6424 34.4686 2533.0 12.42
6 132.7080 34.5018 1375.5 7.04
7 132.6583 34.4951 1320.5 4.61
8 132.7061 34.4969 1263.5 4.38
9 132.6717 34.3732 628.0 14.09
10 132.7671 34.3918 192.5 8.98
11 132.8321 34.4984 50.0 13.24
12 132.5647 34.5064 85.5 24.48
13 132.4238 34.4462 452.0 14.52
14 132.5757 34.4824 792.5 14.47
15 132.8380 34.5109 484.0 24.20
16 132.6769 34.5385 243.0 15.05
17 132.5866 34.4643 211.5 11.67
18 132.4384 34.5220 344.0 14.99
19 132.6111 34.6359 433.0 20.23
20 132.8759 34.6510 609.0 24.29
21 133.0244 34.5655 271.0 16.57
22 132.7437 34.6205 85.0 26.39
23 132.7791 34.7004 71.0 9.44

この表から読み取れること: 強雨時刻 ( 03:00 前後) は速度が小さく重心が安定する一方、 弱雨時刻は速度が跳ねる。重心は 「雨量の多い時刻だけ」信頼してよい指標。

分析3: 時間別 Moran's I (空間自己相関)

狙い

「近くの観測所同士で雨量が似ているか」を 1 数値に要約し、24 時刻でどう変化するかを見る。 雨が 1〜2 か所に集中している時刻は I が高く、分散して降る時刻は I が低い。 仮説 H2 を検証する。

用語: 「Moran's I (モランのアイ)」は空間統計の代表指標。 +1 で 同じような値の場所が固まっている (局所集中)、 0 で 無関係 (ランダム配置)、 −1 で 高低が交互 (チェッカーボード)。 本レッスンでは「Global Moran's I」(県全体の平均値 1 個)を時刻ごとに計算する。

このツールで何ができて、何ができないか(要件 J)

項目このツール
入力観測点の (lat, lon) と各点の値(その時刻の雨量)
出力1 個のスカラー I (約 −1 〜 +1)
主なパラメータ 近傍数 k(本レッスンは k=8)。 小さすぎるとノイジー、大きすぎると遠くまで含めて I が薄まる
限界 (1) 「Global」 = 県全体の平均値 1 個。どこに集中しているかは分からない
(2) k と重み関数 (inverse-distance) の選択で値が変わる
(3) 観測点配置にバイアス (山陰薄) があると I もバイアス
代替 Local Moran's I (LISA, 観測所ごとの値) — どこがホットスポットかが分かる (発展課題)
数式の細部 気にしなくて良い。「近い点同士の値の似具合」を −1〜+1 に正規化した数とイメージすれば十分

1 日のデータがどう変換されるか(Before/After 表、要件 K)

段階内容サイズ
① 1 時間集約データ24 × 観測所数の雨量(24, 313)
② 観測点間の距離行列 (km) 緯経度差を km 換算し、全ペア距離 (313, 313)
③ 各点の k=8 近傍だけ重みを残し、残りはゼロ 近い点ほど大きい重み (1/距離)、行ごとに合計 1 に正規化同左
④ 各時刻で I を計算偏差 z の 近傍と自分の積を全部足す1 個のスカラー
⑤ 24 時刻分時刻別 I の配列長さ 24
⑥ 棒グラフ + 時間総雨量の折れ線図 3

実装(狙いと要点)

狙い: 観測点の k 近傍 inverse-distance 重み行列で I を計算。 要点: 距離は緯経度を km に換算してから計算。重みは行標準化。

L06_july1_heatmap.py 行 881–943

 1
 2
 3
 4
 5
 6
 7
 8
 9
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
def moran_i(values, lats_arr, lons_arr, k=8):
    """k 近傍 (inverse-distance) で Global Moran's I を計算"""
    v = np.asarray(values, dtype=float)
    mask = ~np.isnan(v)
    if mask.sum() < 10 or np.nanstd(v) == 0:
        return np.nan
    v = v[mask]
    la, lo = lats_arr[mask], lons_arr[mask]
    n = len(v)
    # 距離行列 (km)
    dla = (la[:, None] - la[None, :]) * KM_LAT
    dlo = (lo[:, None] - lo[None, :]) * KM_LON
    d = np.sqrt(dla ** 2 + dlo ** 2)
    np.fill_diagonal(d, np.inf)
    # 各点の k 近傍だけ inverse-distance 重みを残す
    W = np.zeros_like(d)
    for i in range(n):
        idx = np.argsort(d[i])[:k]
        W[i, idx] = 1.0 / np.maximum(d[i, idx], 0.1)
    # 行標準化 (各行の合計を 1 に)
    W = W / W.sum(axis=1, keepdims=True)
    z = v - v.mean()
    s2 = (z ** 2).sum() / n
    if s2 == 0:
        return np.nan
    num = (W * np.outer(z, z)).sum()
    return float(num / (s2 * n) * (n / W.sum()))

moran_per_hour = [moran_i(hourly.iloc[h].values, lats, lons, k=8) for h in range(24)]

結果(図と読み取り)

なぜこの図か: I の時刻変化と 時間総雨量同じ時間軸で並列に見たい。 左軸 = I の棒(赤=強・青=中・灰=弱)、右軸 = 総雨量の折れ線。 両者が同期するか/ずれるかが仮説 H2 の核心。

図 3: 時間別 Moran's I (棒) と時間総雨量 (橙線)。同期すれば「雨多い時刻 = 集中」
図 3: 時間別 Moran's I (棒) と時間総雨量 (橙線)。同期すれば「雨多い時刻 = 集中」

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

結果(表と読み取り)

表 2: 24 時刻の Moran's I と総雨量
時刻時間総雨量 (mm)Moran's I解釈
00:008400.160中程度
01:006150.036ほぼ無関係
02:0015270.650強い局所集中
03:0046860.774強い局所集中
04:0039310.430強い局所集中
05:0025330.418強い局所集中
06:0013760.443強い局所集中
07:0013200.226中程度
08:0012640.193中程度
09:006280.597強い局所集中
10:001920.502強い局所集中
11:00500.259中程度
12:00860.240中程度
13:004520.225中程度
14:007920.522強い局所集中
15:004840.465強い局所集中
16:002430.145中程度
17:002120.242中程度
18:00344-0.001ほぼ無関係
19:004330.046ほぼ無関係
20:006090.119中程度
21:002710.438強い局所集中
22:00850.277中程度
23:00710.172中程度

この表から読み取れること: 「強い局所集中」と判定された時刻は雨量も多い傾向。 仮説 H2 への部分支持(同期はするが完全に一致するわけではない)。

分析4: 観測所別ピーク時刻ヒストグラム

狙い

「県内の観測所たちがいつピーク雨量を記録したか」を 1 つのヒストグラムに集約する。 1〜2 の時間帯に観測所が集中していれば 梅雨前線の同時通過を示唆(仮説 H3)。 広く分散していれば 独立した複数のセルが時間差で降ったことを示す。

狙いに対する手法選択(要件 H)

1 日のデータがどう変換されるか(Before/After 表、要件 K)

段階内容サイズ
① 1 時間集約データ24 × 観測所数の雨量(24, 313)
② 各観測所で idxmax()その観測所のピーク時刻 (h)各観測所 1 個
③ 日合計 ≤ 5 mm の観測所は除外「降ってない」観測所のノイズ排除n=313 に減
④ 24 ビンのヒストグラム + CDF図 4

実装(狙いと要点)

狙い: 各観測所のピーク時刻を集計して分布を見る。 要点: 日合計が小さい観測所はピーク時刻に意味がないので除外する。

L06_july1_heatmap.py 行 347–372

 1
 2
 3
 4
 5
 6
 7
 8
 9
356
357
peak_hours = []
for st in geo_cols:
    s = hourly[st]
    if s.sum() > 5:                          # 日合計 5 mm 超だけ採用
        peak_hours.append(int(s.idxmax().hour))
peak_hours = np.array(peak_hours)

# 24 ビンのヒストグラム + 累積分布 (CDF)
counts, edges, _ = ax.hist(peak_hours, bins=np.arange(-0.5, 24.5, 1))
mode_h = int(np.argmax(counts))              # 最頻時間帯
ax2.plot(np.sort(peak_hours), np.arange(1, len(peak_hours)+1)/len(peak_hours)*100)

結果(図と読み取り)

なぜこの図か: 同時多発性を見るには ヒストグラムが定石。 モード(最頻時間帯)を縦線で示し、CDF を併置すると「P25/P50/P75 はいつか」が読める。

図 4: 観測所別ピーク時刻のヒストグラム (左) と累積分布 CDF (右)
図 4: 観測所別ピーク時刻のヒストグラム (左) と累積分布 CDF (右)

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

結果(表と読み取り)

表 3: ピーク時刻 上位 5 時間帯(観測所数の多い順)
時間帯ピーク観測所数全体割合
03:00-03:5913342.5%
04:00-04:598426.8%
05:00-05:59185.8%
20:00-20:59185.8%
01:00-01:59154.8%

この表から読み取れること: 上位 5 時間帯だけで全観測所の過半が説明できる。 雨域の主要なピークはこの数時間に集中していたことが定量的に確認できる。

分析5: Top10 観測所の 10 分値時系列と座標推定

狙い

「日合計上位 10 観測所の波形」を 10 分値で重ね描きし、ピーク集中度を観測所別に見る。 仮説 H5(上位観測所は短時間集中型)を検証。 同じ分析の中で、仮説 H4(属性結合で座標欠落を代替できる)の検証も行う (10 分値は座標を使わないが、「Top10 を地図上に置きたい」発展課題で必要になる)。

STEP 1: 河川名による属性結合 — 座標欠落の代替推定(仮説 H4)

雨量観測所には公式の緯経度が無い。これを補うため、同じ河川にあるカメラの平均緯経度を 代理座標として用いる。fallback 階層は 河川一致 → 水系一致 → 事務所中心の 3 段。
fallback 段階役割マッチ条件誤差の目安
① 河川一致 (最良) 同じ水系の同じ河川にあるカメラの平均緯経度を使う water_system × river 完全一致 数 km 程度(同じ河川の上流〜下流の中間)
② 水系一致 (fallback) 河川マッチが取れない時、水系全体のカメラ平均 water_system のみ一致 10 km 前後
③ 事務所中心 (最終 fallback) 水系も合わない時、事務所の管轄中心 事務所名一致 20 km 程度
④ 未解決 除外して以降の分析対象から外す
表 4: 座標解決ソースの内訳(実データ)
fallback 段階観測所数割合
河川一致 (最良)22756.6%
水系一致 (fallback)00.0%
事務所中心 (最終 fallback)8621.4%
未解決 (除外)8821.9%

この表から読み取れること: 河川一致 (227 観測所) が大半を占め、 未解決は 88 観測所。仮説 H4 への支持: 属性結合だけで KDE/重心/Moran 計算に十分な座標が得られた。

STEP 2: Top10 観測所の 10 分値波形

狙い: 日合計上位 10 観測所を抽出し、10 分値の波形を重ね描き。 ピークがどれくらい鋭いか、複数ピークか単峰かを見る。

1 日のデータがどう変換されるか(Before/After 表、要件 K)

段階内容サイズ
① 10 分値 tidy(144, 観測所数)(144, 313)
day_total = tidy.sum(axis=0)観測所別 日合計長さ 313
③ 上位 10 観測所抽出日合計降順で .head(10)10 観測所名
④ 10 分値の重ね描きx = 時刻, y = 10 分雨量, 色 = 観測所図 5
⑤ 集中度 = ピーク 1 時間 / 日合計波形の鋭さの定量指標10 個のスカラー

実装(狙いと要点)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Top10 抽出と 10 分値の重ね描き
top10_names = day_total[geo_cols].sort_values(ascending=False).head(10).index.tolist()

fig, ax = plt.subplots(figsize=(12, 5))
cmap = plt.get_cmap("tab10")
for i, st in enumerate(top10_names):
    s = tidy[st]
    ax.plot(s.index, s.values, color=cmap(i), alpha=0.85, lw=1.3,
            label=f"{st} (Σ={day_total[st]:.0f}mm)")

# 集中度 = ピーク 1 時間雨量 / 日合計 (1 に近いほど短時間集中型)
for st in top10_names:
    peak_share = hourly[st].max() / day_total[st]

結果(図と読み取り)

なぜこの図か: 上位観測所の 波形の鋭さを見るには 10 分値を 重ね描きするのが最も直感的。 1 観測所 1 線で色分けし、凡例に日合計を出す。波形が短時間に立ち上がる観測所が短時間集中型。

図 5: 日合計上位 10 観測所の 10 分値時系列重ね描き
図 5: 日合計上位 10 観測所の 10 分値時系列重ね描き

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

結果(表と読み取り)

表 5: 日合計上位 10 観測所のサマリ(集中度付き)
観測所 水系 河川 日合計 (mm) ピーク時刻 ピーク時間雨量 (mm) 最大時間/日合計
矢草(砂防) 単独河川 永慶寺川 173.0 03:00 53.0 31%
馬の口 その他 沿岸部 168.0 03:00 35.0 21%
小瀬川ダム 小瀬川 小瀬川 167.0 03:00 50.0 30%
矢草北 その他 沿岸部 159.0 03:00 47.0 30%
矢草南 その他 沿岸部 145.0 03:00 46.0 32%
野貝原(砂防) 単独河川 御手洗川 141.0 03:00 47.0 33%
津田(国) 小瀬川 林川 141.0 03:00 49.0 35%
地御前(砂防) その他 沿岸部 138.0 03:00 33.0 24%
楠那 その他 沿岸部 138.0 04:00 36.0 26%
五日市観音 単独河川 岡ノ下川 135.0 03:00 50.0 37%

この表から読み取れること: 「最大時間/日合計」が 20〜37% に分布 (3 時間で日合計の 6〜9 割が降った計算)。 水系列を見ると上位は 「単独河川」「その他(沿岸部)」「小瀬川」に偏っており、 県西部沿岸〜山地のラインに集中する地形性降水のサイン。 発展課題(地形・標高との照合)への伏線になる。

仮説検証と考察

仮説と結果の照合

#仮説判定根拠
H1 雨域は梅雨前線の進行に従い数時間で県内を抜ける 部分支持 図 1 (KDE) と図 2 (重心軌跡) で雨域は確かに移動するが、西→東への単調進行ではなく、 複数のセルが時間差で入れ替わる動き。 重心の総移動 ≒ 334 km。
H2 強雨時間帯ほど雨は局所集中する (Moran's I が高い) 部分支持 図 3 で I が高い時刻 ≒ 強雨時刻という同期傾向は見える。 最大 I = 0.77 @ 03:00。 ただし強雨でも I が中程度の時刻もあり、雨域が 2 セル併存するパターンが影響。
H3 観測所ごとのピーク時刻は 1〜2 の時間帯にモードを持つ 支持 図 4 ヒストグラムでモード時刻 03:00 に 133 観測所が集中。 P25-P75 = 3.0h-4.0h と 狭い幅 → 県全体で同時多発的にピーク。
H4 河川名属性をキーにカメラと結合すれば代理座標が得られる 支持 表 4 で河川一致が 227 観測所、未解決はわずか 88。 KDE/重心/Moran 計算に十分。 誤差は数 km〜十数 km だが県全体スケールの分析には十分。
H5 日合計上位 10 観測所は短時間集中型の波形 部分支持 表 5 で「最大時間/日合計」がおおよそ 20〜37% (3 時間で日合計の 6〜9 割を占める観測所が多い)。 24 時間均等分散ではないが、1 時間に集中する極端パターンでもない。 実際には 2〜4 時間の連続強雨がその日の大半を占めていた。

考察

発展課題(結果から導かれる新たな問い)

各課題は、上の 結果新しい仮説に裏打ちされている。 「結果 X → 新仮説 Y → 課題 Z」の 3 段で書く。

  1. 多日比較で前線の動きの再現性を見る
    • 結果 X: 図 2 の重心軌跡は 2024-07-01 に固有のパターン。前線通過のたびに同じ動きをするのか不明
    • 新仮説 Y: 14 日窓の他の豪雨日 (06-30, 07-02 など) の重心軌跡を重ねると、 梅雨前線の典型的進行方向が浮かび上がるはず(ベクトル場として可視化)
    • 課題 Z: rain_2024 ディレクトリの 14 日分について同じ重心計算を行い、 14 本の軌跡を 1 枚に重ねて方向の主成分を取る (PCA)
  2. Local Moran's I でホットスポットを特定
    • 結果 X: 図 3 の Global I は 「県全体での集中度」1 個しか示さず、 具体的な集中地点が分からない
    • 新仮説 Y: 観測所ごとに Local Moran's I (LISA) を計算すれば、 HH (高×高クラスタ) / LH (Outlier) / LL (低×低クラスタ) として 地図上で どこが豪雨セルの中心かが直接読めるはず
    • 課題 Z: PySAL の esda.Moran_Local で計算 → 4 タイプを地図に色分け。 最強雨時刻 (03:00) で確認
  3. KDE バンド幅の感度分析
    • 結果 X: 図 1 は h=0.07° で固定だが、強雨セルのサイズは時刻で変わる可能性がある
    • 新仮説 Y: 各時刻で 適応的バンド幅 (Silverman's rule や交差検証) を使えば、 強雨時刻ほど自動的に細かい解像度になり、KDE の見かけが変わるはず
    • 課題 Z: scipy.stats.gaussian_kdebw_method を変えて h=0.03/0.07/0.15 の 3 通りを並列描画。差分から「現象スケール」が読めるかを検証
  4. 観測所→流域水位ピーク時刻のラグ
    • 結果 X: 図 4 で観測所のピーク時刻は 03:00 にモード。 これに対し河川水位ピークは何時間遅れるのか不明
    • 新仮説 Y: 観測所ピーク → 河川水位ピークの 時間ラグは流域面積でスケールする (大きい流域ほど遅れて応答)。観測所と水位観測所をペアにして散布すると単調関係が見える
    • 課題 Z: 水位 10 分値データ (DoBoX 1276 系) を取得し、流域別にピーク時刻を取って 雨量ピーク時刻との差分を散布。流域面積 (河川シェイプ) と重ね合わせる
  5. Top10 観測所の地形配置と短時間集中度の関係
    • 結果 X: 表 5 で上位観測所は特定の水系・河川に偏り、最大時間/日合計が高い (短時間集中型)
    • 新仮説 Y: 短時間集中型の観測所は 急峻な谷に位置するはず(地形性降水)。 標高や傾斜と相関するはず
    • 課題 Z: 標高 DEM (DoBoX) を取得し、Top10 観測所の代理座標で 標高・傾斜を抽出。最大時間/日合計と散布図で相関を取る