災害時に従業員一人ひとりの避難情報（警戒レベル）を地図で可視化

従業員の自宅と避難情報が発表されている地域の関係を、Python/Jupyter Notebook を使って可視化するためのツール（？）を作成しました。単純に、避難情報が発表/発令された地区の地理的・時系列的な広がりを可視化するためにも使用できます。

https://github.com/ttsukagoshi/employee-evac-map

:::note info
本記事では、2023年7月15日から16日朝にかけて秋田市で発表された避難情報を例にしています。
:::

![警戒レベルに応じて色分けされた従業員ごとのマーカーがプロットされた地図のスクリーンショット画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/726523/f07de7ec-6502-4f4d-04ae-0f51d34c57e7.png)

## こんな人におすすめ
- 会社のリスク対策担当
- 人事担当

「システム担当専用」というのではなく、PythonとJupyter Notebookに関する最低限の知識さえあればどの職種の人でも使えるように、と意識してみました。（私自身、Pythonを学び始めて2年目です）

利用場面としては、災害の事前〜事中を想定しています。影響範囲を地理的・視覚的に把握することで、翌日以降の全社的な営業可否判断や出社要否判断の助けとしたり、従業員ごとの個別支援に使えるのではと思っています。

## 個人情報保護への配慮

従業員ごとの住所をプロットするということで、住所ごとに緯度・経度を設定することもできます。ただ、そうすると

- 作成した地図が直接的な個人情報を含むことになるので、社内会議と言えど資料としての共有範囲が限られてしまう
- 準備段階で、住所ごとの緯度・経度リストを作成しておく必要がある

といった課題があるので、ここでは従業員の住所は**大字・町丁目**単位で扱うことにしています。この単位であれば、**自治体の避難情報と粒度が揃う**上、国土交通省が提供する[国土数値情報ダウンロードサイト](https://nlftp.mlit.go.jp/cgi-bin/isj/dls/_choose_method.cgi)の**位置参照情報で代表地点の座標を取得できる**ので、何かと便利です。

:::note warn
言わずもがなですが、実際に使用される際には、個人情報を含む実データをcommitしないよう、十分にご留意ください。
:::

:::note info
本レポジトリでは、[Faker](https://faker.readthedocs.io/en/master/)を使って作成した架空の従業員300名分のデータを使用しています。本稿スクリーンショット内に表示されているものを含めて、実在の人物・住所とは関係ありません。（避難情報は実際に発表されたものです）
:::

## 【事前】下準備

### 実行環境の準備

Python 3.x の最新版をインストール（[Download Python | Python.org](https://www.python.org/downloads/)）

GitHubレポジトリのコピーをローカルに作成

:::note info
「Git って...？」という方には[レポジトリのトップ](https://github.com/ttsukagoshi/employee-evac-map)から`Code` > `Download ZIP`が一番シンプルかと思いますが、`fork`や`git clone`など他の方法をご存知の方はお好きにどうぞ
![「Code」から「Download ZIP」のメニューを表示した画面のスクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/726523/56d2df61-b5ac-163b-d469-5fabc343f3e7.png)
:::

ローカルに作成したフォルダに移動して、以下のコマンドから Python の仮想環境を作成
```
python -m venv env
```

仮想環境を有効化

```
# Windows
env\Scripts\activate

# macOS/Linux
source env/bin/activate
```

必要なパッケージをインストール

```
pip install -r requirements.txt
```

### 必要なデータを準備しておく

平時のうちに、マッピングのために必要なデータをあらかじめダウンロード・整形して、`data`フォルダに保存しておきます。

#### 大字・町丁目ごとの位置参照情報（代表地点の緯度・経度）

国土交通省が提供する[国土数値情報ダウンロードサイト](https://nlftp.mlit.go.jp/cgi-bin/isj/dls/_choose_method.cgi)から、必要な市町村について、最新の位置参照情報を CSV として取得・保存しておく（ナビゲーションメニューから`位置参照情報` > `データダウンロード`）。

:::note info
位置情報の粒度はいくつか種類がありますが、避難情報の発表単位と揃えるため、ここでは大字・町丁目単位のデータをダウンロードします（[`data/akita-2022-ichijoho-utf8.csv`](https://github.com/ttsukagoshi/employee-evac-map/blob/main/data/akita-2022-ichijoho.csv)）。
:::

データの形式は次のようになっています。以降、国土数値情報ダウンロードサイトからダウンロードしたファイルの形式をそのまま使用します：

| 都道府県コード | 都道府県名 | 市区町村コード | 市区町村名 | 大字町丁目コード | 大字町丁目名   | 緯度      | 経度       | 原典資料コード | 大字・字・丁目区分コード |
| -------------- | ---------- | -------------- | ---------- | ---------------- | -------------- | --------- | ---------- | -------------- | ------------------------ |
| 5              | 秋田県     | 5201           | 秋田市     | 52010001000      | 旭川清澄町     | 39.743039 | 140.128123 | 0              | 1                        |
| 5              | 秋田県     | 5201           | 秋田市     | 52010002000      | 旭川新藤田西町 | 39.740677 | 140.12612  | 0              | 1                        |

:::note info
ダウンロードしたファイルは、文字エンコードが Shift JIS になっています。Windows 端末だけで作業や情報共有が完結するのであればあまり不便はありませんが、macOS など、他の OS 端末でも操作・閲覧することを考えてここでは UTF-8 に変換しておきます。

```
# macOS
iconv -f SHIFT_JIS -t UTF-8 input.csv > output.csv
```
:::

#### 従業員の自宅住所一覧

従業員の住所一覧をCSV形式で保存します。大字・町丁目の表記は、先にダウンロードした位置参照情報のものと揃えておきます。

:::note info
ここでは例として、300名分のダミーデータ[`data/mock_employee_list.csv`](https://github.com/ttsukagoshi/employee-evac-map/blob/main/data/mock_employee_list.csv)を使用しています。ダミーデータは、[Faker](https://faker.readthedocs.io/en/master/)を使って[`scripts/employees.py`](https://github.com/ttsukagoshi/employee-evac-map/blob/main/scripts/employees.py)で生成しました。
:::

## 【事中】時系列での避難情報を記録

自治体が提供する防災メールサービスなどから得た避難情報をスプレッドシートなどに記録していき、マップ描画時には、CSVとして出力します。（例では[`data/akita_evac_all.csv`](https://github.com/ttsukagoshi/employee-evac-map/blob/main/data/akita_evac_all.csv)）。

マップは、災害がまさに発生している事中にリアルタイムで更新していくことも想定しているので、このCSV出力の段階では特に時点などを区切る必要はありません。

:::note info
自治体や第三者が提供するウェブAPIを使って、避難情報そのものを自動で取得することができる場合もあります。秋田市には、2023年7月現在でそのような自治体が提供するAPIサービスはなく、公式の防災メールから手動でスプレッドシートに内容を落とし込みました（参考：[防災ネットあきた｜秋田市公式サイト](https://www.city.akita.lg.jp/bosai-kinkyu/1009827.html)）。
:::

CSV の例（[`data/akita_evac_all.csv`](https://github.com/ttsukagoshi/employee-evac-map/blob/main/data/akita_evac_all.csv)）：

| MAIL_TIMESTAMP | LEVEL | LEVEL_NAME | REASON | BLOCK_ORIGINAL | BLOCK      |
| ----------------- | ------- | ------------ | -------- | ---------------- | ------------ |
| 2023/7/15 7:25:00 | 3       | 高齢者等避難 | 洪水     | 牛島東六丁目     | 牛島東六丁目 |
| 2023/7/15 7:25:00 | 3       | 高齢者等避難 | 洪水     | 仁井田小中島     | 仁井田小中島 |
| 2023/7/15 7:25:00 | 3       | 高齢者等避難 | 洪水     | 仁井田字新中島   | 仁井田       |
| 2023/7/15 7:25:00 | 3       | 高齢者等避難 | 洪水     | 仁井田字西潟敷   | 仁井田       |

- 時点情報は、発表時点や配信時点などいくつか考え方がありますが、ここでは情報を入手した時点を意思決定の時点と捉えて、防災メールの受信日時を時点として扱います（`MAIL_TIMESTAMP`列）。
- `LEVEL`及び`LEVEL_NAME`列は全国共通の警戒レベルを指します。（参考：[「警戒レベル4」で危険な場所から全員避難！5段階の「警戒レベル」を確認しましょう | 暮らしに役立つ情報 | 政府広報オンライン](https://www.gov-online.go.jp/useful/article/201906/2.html)など）
- `REASON`列には、避難の理由（洪水、土砂災害、高潮、地震、津波、火山 etc.）を記載します。
- 秋田市の防災メールでは`BLOCK_ORIGINAL`列にあるとおり、字単位での避難情報が発表されますが、国土数値情報ダウンロードサイトには位置情報（緯度・経度）がないため、大字・町丁目単位にまとめておきます（`BLOCK`列）。

:::note warn
**実際の災害時には、複数の情報収集チャンネルを持っておくことをおすすめします。** 自治体によっては防災メールの発信が他システムと連動しておらず、手動というケースもあります。そうなると防災メール記載の内容に誤りがあったり、発信のタイミングが遅くなったりするので、[NHK ニュース・防災アプリ](https://www3.nhk.or.jp/news/news_bousai_app/index.html)や[ウェザーニュース](https://weathernews.jp/app/)などのアプリ上での通知のほうが早かったりもします。公務員も、どうやら人間のようです。
:::

:::note info
列名を変更することもできますが、その場合は[`employee-evac-map.ipynb`](https://github.com/ttsukagoshi/employee-evac-map/blob/main/employee-evac-map.ipynb)内の、列名で情報を参照している箇所も変更する必要があります。
:::

## 【事中・事後】地図の描画

[`employee-evac-map.ipynb`](https://github.com/ttsukagoshi/employee-evac-map/blob/main/employee-evac-map.ipynb)を Jupyter Notebook で開きます。

```
juptyer notebook employee-evac-map.ipynb
```

まず、ファイル名などの変数を調整します（ほとんどの項目は災害発生前に、事前に調整しておけます）。実際の地図描画は[Folium](https://python-visualization.github.io/folium/)を使っているので、その関連での調整や、参照するファイルのパスが主なものです。

```python
import os

# データの保存先ディレクトリ
DATA_DIR = "data"

# 地図の保存先ディレクトリ
MAP_DIR = "maps"

# 国土数値情報ダウンロードサイトから取得した位置参照情報のCSVファイルのパス
BLOCK_POSITIONS_FILE_PATH = os.path.join(DATA_DIR, "akita-2022-ichijoho.csv")

# 従業員の住所一覧のCSVファイルのパス
EMPLOYEE_ADDRESS_FILE_PATH = os.path.join(DATA_DIR, "mock_employee_list.csv")

# 避難情報のCSVファイルのパス
EVAC_INFO_FILE_PATH = os.path.join(DATA_DIR, "akita_evac_all.csv")

# マッピングする時点一覧 yyyy-MM-dd hh:mm:ss
MAPPING_DATETIME_LIST = [
    "2023-07-15 09:00:00",
    "2023-07-15 11:00:00",
    "2023-07-15 13:00:00",
    "2023-07-15 15:00:00",
    "2023-07-15 17:00:00",
    "2023-07-15 19:00:00",
    "2023-07-16 05:00:00",
]

# 描画する地図の、中心地点の緯度・経度
MAP_CENTER = [39.716719, 140.129775]  # ここでは秋田駅

# 描画する地図の、初期のズームレベル
MAP_ZOOM_START = 11

# 描画する地図の様式
# https://python-visualization.github.io/folium/modules.html
MAP_TILES = "Stamen Terrain"  # "OpenStreetMap" "Stamen Terrain" "Stamen Toner" "Stamen Watercolor" "CartoDB positron" "CartoDB dark_matter"

# 描画する地図に表示する、会社の所在地などのマーカー
# 本社だけでなく、支社や営業所などを複数表示することもできる
# 逆に何も追加で表示したくない場合は、空のリストにする
MAP_MARKERS = [
    {
        "location": [39.719007, 140.102866],  # 緯度・経度。ここでは秋田県庁
        "popup": "秋田県庁",  # 地図上で表示される文字列
        "icon": "building",  # https://fontawesome.com/icons
        "color": "darkgreen",  # https://python-visualization.github.io/folium/modules.html
    },
    {
        "location": [39.800408, 140.218396],
        "popup": "旭川ダム",
        "icon": "water",
        "color": "darkgreen",
    },
]

# 描画する地図に表示する凡例
# [[datetime_string]]は、MAPPING_DATETIME_LISTの各要素の文字列に置換される
MAP_LEGEND = """<div style="position: fixed; bottom: 50px; left: 50px; width: 240px; height: 120px; 
     border:2px solid grey; z-index:9999; font-size:14px;
     background-color: white;
     ">&nbsp; 避難レベル ([[datetime_string]])<br>
     &nbsp; 3 (高齢者等避難) &nbsp; <i class="fa fa-map-marker fa-2x" style="color:red"></i><br>
     &nbsp; 4 (避難指示) &nbsp; <i class="fa fa-map-marker fa-2x" style="color:purple"></i><br>
     &nbsp; 5 (緊急安全確保) &nbsp; <i class="fa fa-map-marker fa-2x" style="color:black"></i>
      </div>
     """
```

## 実際に描画した地図の例
単純に、避難情報の発表状況を地図に落とし込んだもの:
![2023年7月16日午前5時時点で秋田市内に発表されていた避難情報を地図に落とし込んだ画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/726523/4adf05ba-d024-e355-944c-3436b4fdb8b3.png)

従業員ごとの避難情報（警戒レベル）を地図に落とし込んだもの:
![2023年7月16日午前5時時点で秋田市内に発表されていた避難情報に基づいて、従業員の住所を色別で地図に落とし込んだ画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/726523/5aefb5b6-48e3-431b-3694-e0bb49296fdc.png)

実際のコードにご興味があれば、ぜひGitHubレポジトリをご覧ください：

https://github.com/ttsukagoshi/employee-evac-map

Foliumを使った地図描画や、その前段階のデータ処理に関わるものは、ディレクトリ直下の[`employee-evac-map.ipynb`](https://github.com/ttsukagoshi/employee-evac-map/blob/main/employee-evac-map.ipynb)に含まれています。