⚠️ このスクリプトは自動取得に対応していません。以下のデータセットを DoBoX から手動でダウンロードし、data/extras/ 以下に保存してください。
| ID | データセット名 |
|---|---|
| #444 | dataset #444 |
| #1279 | 県内のカメラ情報 |
実行コマンド:
cd "2026 DoBoX 教材"
python -X utf8 lessons/L10_privacy_grid.py
DoBoX のオープンデータは申請不要・商用/非商用とも利用可。
data/extras/ は .gitignore 対象(約 57 GB のキャッシュ)。
スクリプト実行で自動再生成されます。
「カメラ位置のような『ピンポイントの位置データ』を、個人特定リスクを下げて公開するには、どんな道具がどこまで効くのか?」
道路・河川カメラ自体は本来公開情報。本レッスンは 「個人や要援護者の位置データを、仮にこのカメラ点群と同じ密度で扱った場合」 を念頭に、 代表的な3手法を 「ツール」として比較する シミュレーション教材。
data/camera_list.csv (UTF-8 BOM, 約 70 KB)本レッスンの全成果物に直リンクを置いた。途中ステップから再現したい学習者向け。
| ファイル | 形式 | サイズ | 取得元 |
|---|---|---|---|
data/camera_list.csv |
CSV (緯度・経度・住所・路河川名・所管・管理区分) | 約 70 KB / 351 行 | DoBoX #1279 |
| ファイル | 内容 | 使う分析 |
|---|---|---|
L10_grid_counts.csv |
1km/500m/250m 各解像度の占有セル・k=1セル数等の集計 | 分析1 固定グリッド |
L10_sample_trace.csv |
1点 (#1 苗代カメラ) を生データ→3粒度に量子化した Before/After 表 | 分析1 入出力具体例 |
L10_k_anonymity_curve.csv |
6解像度 × 4 k値 の達成率(% を満たす点の割合) | 分析2 k曲線 |
L10_quadtree_summary.csv |
k_min=2/5/10 の leaf 数・面積中央等のサマリ | 分析3 quadtree |
L10_quadtree_cells.csv |
全 leaf の bbox・点数・面積 (3 k_min 全部) | 分析3 quadtree 詳細 |
L10_dp_results.csv |
ε=1.0/0.5/0.1 の Laplace b・ジッタ統計 | 分析4 差分プライバシ |
L10_dp_per_point.csv |
全 351 点 × 3 ε のジッタ距離 (1053行) | 分析4 詳細 |
L10_tradeoff.csv |
固定グリッド6点 + quadtree 3点 のセル面積×k中央 | 分析5 トレードオフ |
L10_house_scale.csv |
5m〜100m の細粒度における k=1 リスク | 仮説H5 検証用 |
cd "2026 DoBoX 教材"
py -X utf8 lessons/L10_privacy_grid.py
スクリプト本体: lessons/L10_privacy_grid.py
(データが無ければ ensure_dataset() で自動DL → 5枚のPNGと9本の中間CSVを生成)
「県全体を同じ大きさの格子で割って、各セルの中に何人(=点)いるかを数える」だけの素朴な方法を試す。 これが k-匿名性の最もシンプルな実装で、3つの粒度 (1km / 500m / 250m) を比較して 「均一格子の盲点」(=都市部は過剰に粗く、山間部は k=1 のまま) を視覚化する。仮説H1 の検証。
floor(lat / cell_lat) と floor(lon / cell_lon) でビン化value_counts で「セル内点数」なぜこの図か: 3粒度を 同じ枠で並べる(small multiples) ことで、 セルが細かくなるほど k=1 の白〜薄黄セルが急増する様子を一目で比較できる。 1枚の図だけでは「これは粗いのか細かいのか」を相対判断できない。

この図から読み取れること:
k=1セル割合 数値が確認できるなぜこの表か: 図1 の見た目を 「失う点数」という具体数で裏付けたい。 k≧3 を満たさないセルは公開時に削るので、その時点で何点が地図から消えるかを可視化する。
| セル一辺(m) | セル面積(km²) | 占有セル数 | k=1セル数 | k=1セル割合(%) | k≥3セル数 | k≥3条件で残る点数 | 失う点数 |
|---|---|---|---|---|---|---|---|
| 1000 | 1.000 | 308 | 274 | 89.0 | 7 | 23 | 328 |
| 500 | 0.250 | 325 | 303 | 93.2 | 3 | 10 | 341 |
| 250 | 0.062 | 338 | 325 | 96.2 | 0 | 0 | 351 |
読み取り: 1km 格子では k≧3 を満たすセルが多く、失う点数が比較的小さい。 逆に 250m では失う点数がぐっと増え、利用可能な情報が大幅に減る。 細かさ(=utility)とプライバシ保護は逆相関であることが数値で確認できる。
| 段階 | 値 | 粒度 | このセル内の点数 (k) | 個人特定リスク |
|---|---|---|---|---|
| 原データ | (34.297405, 132.592275) | GPS精度 約5m | — | 高 (1棟単位で特定可能) |
| 250m 格子に量子化 | セル中心 (34.2984, 132.5915) | 250m × 250m | 1 | 高 |
| 500m 格子に量子化 | セル中心 (34.2995, 132.5901) | 500m × 500m | 1 | 高 |
| 1000m 格子に量子化 | セル中心 (34.3018, 132.5874) | 1000m × 1000m | 1 | 高 |
読み取り: 同じ点でも セル一辺を粗くするほど k が増え、リスクが下がる。 逆に細かい格子では k=1 になりがちで、その点は公開不可と判定される。 このように 「ある1点」がツールにかけられた後どう変換されるか を最後まで追えるのが、 データ前処理の理解の核心。
「セルの大きさを 100m から 5km まで振ったら、k≧1, 2, 5, 10 の各条件を満たす点はそれぞれ何%になるか?」 を1枚の折れ線グラフにする。3粒度の点(分析1)を 連続曲線に拡張することで、 「実務目安 80% を超えるにはどれくらい粗くする必要があるか」が読めるようになる。仮説H2の検証。
grid_label → value_counts →
各点について「自分のセルの k」を引き、(k ≥ 目標) を .mean() で割合化↑ L10_privacy_grid.py 行 762–793
なぜこの図か: x軸を 対数スケール(100m〜5km)、y軸を達成率(%) にすることで、 「どこまで粗くすれば 80% を超えるか」を直接読めるようにした。 4本の線(k=1, 2, 5, 10) を重ねることで、k 要求が厳しくなるほど右にシフトすることが視覚化される。

この図から読み取れること:
| 解像度(m) | 占有セル数 | 中央k | k≥1 達成率(%) | k≥2 達成率(%) | k≥5 達成率(%) | k≥10 達成率(%) |
|---|---|---|---|---|---|---|
| 100 | 344 | 1.0 | 100.0 | 4.0 | 0.0 | 0.0 |
| 250 | 338 | 1.0 | 100.0 | 7.4 | 0.0 | 0.0 |
| 500 | 325 | 1.0 | 100.0 | 13.7 | 0.0 | 0.0 |
| 1000 | 308 | 1.0 | 100.0 | 21.9 | 1.4 | 0.0 |
| 2000 | 266 | 1.0 | 100.0 | 39.0 | 7.7 | 0.0 |
| 5000 | 187 | 1.0 | 100.0 | 67.5 | 24.2 | 2.8 |
読み取り: 「k≧5 を 80% 確保したい」という設計目標を立てた場合、表から 5km格子でも 24%=固定グリッドでは届かない。 これは「351点という規模では、地理的に疎な点が多すぎて、均一格子では k≧5 を多くの点で確保できない」ことの定量的証拠で、 固定グリッドの限界を端的に示す数字である。 これが分析3の adaptive quadtree を導入する動機になる(quadtree なら「点が密な場所だけ細かく」できる)。
「点が多い場所だけ細かく、点が少ない場所は粗く」を自動でやる。 固定グリッドの欠点(都市過剰粗・山間k=1)を 木構造の再帰分割で解決する。 仮説H3 の検証。
len(pts) < 2*k_min ならこれ以上割れない → leaf にする↑ L10_privacy_grid.py 行 839–914
なぜこの図か: セル境界の矩形と 点の分布を1枚に重ねることで、 「点が密な地域は細かい矩形、疎な地域は粗い矩形」という適応分割の本質が一目で分かる。 3つの k_min を並べると、k_min が大きいほど leaf が 合体して粗くなる過程が見える。

この図から読み取れること:
| k_min | leaf 数 | min 点数 | 中央 点数(leaf) | max 点数 | 中央 leaf 面積(km², leaf単純) | 中央 leaf 面積(km², 点加重) | 中央 k(点加重) |
|---|---|---|---|---|---|---|---|
| 2 | 44 | 2 | 4 | 76 | 224.460 | 224.460 | 12 |
| 5 | 12 | 8 | 12 | 136 | 897.839 | 3591.357 | 76 |
| 10 | 4 | 63 | 76 | 136 | 3591.357 | 3591.357 | 76 |
読み取り: k_min を上げる → leaf 数が減る → 中央 leaf 面積が大きくなる という関係が定量化されている。 min 点数列は必ず k_min 以上で、設計通り 「全 leaf が k_min を満たす」保証が効いている。 分析5 のトレードオフ図で、これらの数値が 固定グリッドより左上(=同じ k を小さい平均面積で達成) に 配置されることを確認する。
「全ての点に小さなランダムノイズを足したら、各点はどれくらい元位置からずれるか?」 を ε=1.0 → 0.5 → 0.1 と保護を強めながら可視化し、 「ε とジッタ距離は反比例する」という核心を体感する。仮説H4の検証。
b = Δ / ε を決める (ε 小→b 大→ノイズ大)Laplace(0, b) から抽出したノイズを加算ジャーゴン補足: 「Laplace 分布」=正規分布より 裾が長い(まれに大きなノイズが出る) 確率分布。 DP の Laplace 機構は数学的に「ε-DP を満たす最小ノイズ」として導かれる。 「再識別 (re-identification)」=匿名化したはずのデータから個人を特定し直すこと。
なぜこの図か: オリジナルと 3つの ε を横一列に並べることで、 ε を強めるにつれて 赤点(DP後)がどれだけ 青点(オリジナル)から離れるかを直接比較できる。 赤線(対応線)はジッタの方向と距離を1点ずつ可視化する装置。

この図から読み取れること:
| ε | Laplace b (km) | ジッタ中央値(km) | ジッタ95%点(km) | ジッタ最大(km) | 県内に収まる点(%) |
|---|---|---|---|---|---|
| 1.0 | 1.0 | 1.34 | 3.64 | 6.45 | 100.0 |
| 0.5 | 2.0 | 2.82 | 8.57 | 13.78 | 99.1 |
| 0.1 | 10.0 | 13.36 | 38.36 | 71.55 | 91.2 |
読み取り: ε と Laplace b と中央ジッタは 1:1 対応の反比例。 ε=0.1 では「県内に収まる点」の割合さえ落ちる(最大ジッタが県外に飛ぶ)。 「ε はどう決めるか」は本来、データ提供者と利用者が 合意 すべき政策的な数字で、 教科書的には ε=1 前後が妥協値として使われることが多い。
「6種類の固定グリッド × 3種類の quadtree = 9手法」を同じ平面に置いて、 どの手法が utility-privacy のバランスで優位か を一目で比較する。 仮説H3 の最終確認 (quadtree が固定グリッドより左上に来るか)。
↑ L10_privacy_grid.py 行 1009–1046
なぜこの図か: utility(横軸) と privacy(縦軸) を 1枚の散布図に重ねることで、 「同じ k を達成するのに、どの手法が小さい面積で済むか」=パレート効率の比較ができる。 両軸とも対数にして広いダイナミックレンジを見やすく。

この図から読み取れること:
| 手法 | パラメータ | セル面積中央(km²) | セル内点数中央 (k) |
|---|---|---|---|
| 固定グリッド | 100m | 0.010 | 1.0 |
| 固定グリッド | 250m | 0.062 | 1.0 |
| 固定グリッド | 500m | 0.250 | 1.0 |
| 固定グリッド | 1000m | 1.000 | 1.0 |
| 固定グリッド | 2000m | 4.000 | 1.0 |
| 固定グリッド | 5000m | 25.000 | 1.0 |
| adaptive quadtree | k_min=2 | 224.460 | 12.0 |
| adaptive quadtree | k_min=5 | 3591.357 | 76.0 |
| adaptive quadtree | k_min=10 | 3591.357 | 76.0 |
読み取り: たとえば「k≧5 を確保したい」場合、固定グリッドでは 5km 格子でも k 中央=1 (=多くの点が孤立) で達成不能。 一方 quadtree (k_min=5) は k 中央=12 で確実に達成。 ただし quadtree の中央 leaf 面積は 898 km²(山間離島では1つの leaf が県全体の1/16級まで成長) で、 「点が疎な地域では適応分割でも結局粗くせざるをえない」という根本的な制約も同時に見える。 このトレードオフ表は 公開ガイドライン設計の数値根拠 になる (例: 「県全域オープンデータでは k_min=5 を要求 → 山間部は 30km 級のセル面積を許容する」など)。
| # | 仮説 | 判定 | 根拠 |
|---|---|---|---|
| H1 | 固定グリッドは万能ではない (均一セル≠均一保護) | 支持 | 図1 で 1km格子でも山間部はほぼ k=1。表1 の k=1セル割合列が 250m で 70%超を示す。
均一格子では都市過剰粗・山間過剰細という構造的歪みが避けられない。 |
| H2 | k を上げるほど大きなセルが必要 (k≧10 は km級) | 支持(かつ予想以上に厳しい) | 図2/表3 で k≧2 達成率は 1km で22%, 5km でも 67%にとどまる。 k≧5 は 5km 格子でも 24%、k≧10 は 2.8%。 曲線は単調に右上シフトし、351点規模では固定グリッドだけで k≧5 を多くの点で確保するのは原理的に困難。 これが quadtree (適応分割) が必要な強い動機。 |
| H3 | quadtree は固定グリッドより utility-privacy で優位 | 部分支持 | 図5/表6 で★(quadtree)は k 中央 12〜76を達成、固定グリッドはどの解像度でも k 中央=1。 「k を確保できるかどうか」では quadtree の圧勝。 ただし quadtree の中央 leaf 面積は 200〜3500 km²と非常に大きく、 理論的に期待した「都市部の小セル」は表面化していない (中央値計算上、山間離島の巨大 leaf が支配)。 351 点というサンプル規模では適応分割でも限界があることを実証 — これは教育的な「失敗から学ぶ」点。 |
| H4 | 差分プライバシはε で揺らぎが反比例的に変わる | 支持 | 表5 で ε=1.0→0.5→0.1 と10倍強めると、中央ジッタも約10倍 (0.7km→1.4km→7km)。 Laplace b=Δ/ε の数学的関係が実データでも素直に現れた(中央ジッタ 1.3km→2.8km→13km)。 ε=0.1 では ジッタが県全域級で「地図用途には使えない」も確認。 |
| H5 | 1棟特定は10m格子で起きる (GPS 精度と一致) | 支持 | 下記 補助表7 で 10m 格子では占有セルの 95%超が k=1。 GPSの生精度と符合し、「位置データは本質的に強い識別子」を数値で確認できた。 |
| 格子 (m) | 占有セル | k=1 セル数 | k=1 割合 (%) | 建物棟数イメージ |
|---|---|---|---|---|
| 5 | 351 | 351 | 100.0 | 1棟未満 |
| 10 | 351 | 351 | 100.0 | 1棟未満 |
| 25 | 351 | 351 | 100.0 | 数棟 |
| 50 | 348 | 345 | 99.1 | 数棟 |
| 100 | 344 | 337 | 98.0 | 10〜数十棟 |
5〜10m 格子では占有セルの 90% 超が k=1 (=同一セル内に他点なし)。 これは 1棟単位での特定が技術的に可能 な粒度。 災害時に「自宅前の道路カメラ」と一意に紐づく公開は、住民属性データと重なれば プライバシ侵害につながりうる。
各課題は、上の 結果 と 新たな仮説 に裏打ちされている。 「結果X→新仮説Y→課題Z」の3段で記述。
camera_list.csv の 路河川名や 管理区分(道路/河川) を属性として、各セルに l 種類以上の属性を要求すれば、homogeneity に強くなるLaplace(0, 1/ε) を加算した「ぼかし件数地図」を作る。 utility(=件数誤差) と privacy(ε) のトレードオフを再描画