Power BIで市区町村別塗分け地図を作ってみる

# はじめに
Power BI でデータ可視化をしていると、地図情報とマッピングして表現したいなぁと思うこともあるかと思います。標準ビジュアルだと場所を丸印で指定するマップビジュアルと塗分け地図の二種類があるので、いずれかを使ってレポート作れそうな印象かと思います。
塗分け地図を利用すると国や県別でエリアを塗分けてくれるので使いやすいなぁと思っていたのですが、市区町村で塗分けが期待通りに動かないケースがあります。
本投稿ではそんな悩みを抱える皆様に市区町村で塗分け地図を作成する一例を紹介します。

# 埼玉県の市区町村ごとの人口を塗分けした例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/93a2dbaa-0dfd-291d-9ad0-fb4c22aaba62.png)


# 準備するもの

## 1. 市区町村別に区切られた地図の準備

まずは市区町村別の地図を準備します。
既存のシェイプファイルがある場合にはこの手順はスキップ可能です。

地図情報は国土交通省が公開している国土数値情報ダウンロードサイトからダウンロード可能です。

https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N03-v3_1.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/258b0b12-305b-73e6-0cb7-52581a52f855.png)

画面をスクロールすると各都道府県の地図情報がダウンロード可能なので今回は埼玉県の地図情報（N03-20230101_11_GML.zip）をダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/c108fa1b-e121-7d59-6172-ccd1198b2a4c.png)



## 2. シェイプファイルをTopo-JSON形式に変換

Power BI で利用可能なファイル形式Topo-JSON)にダウンロードしたシェイプファイルを変換します。

mapshaper サイトアクセスしファイル変換
シェイプファイルをTopo-JSON形式に変換可能なサイトmapshaper へアクセスし,ダウンロードしたZipファイルを"Drop or pasete files here"にドラッグ& ドロップ

https://mapshaper.org


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/db725d74-6f93-973b-e116-f522b380ee0c.png)

ダイアログが表示されるので"Import"をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/8dc41427-5009-c0cd-819b-b7a9f8f6bf46.png)


地図情報がよみこまれました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/e370166a-4892-4954-8346-cd12c22705aa.png)

読み込まれた地図情報は細かい情報まで入っているので、Power BIではもう少し単純化（サイズを小さく）した情報でOKなので、単純化処理をします。
画面右上の"Simplify"　-> "Apply" を選択してサイズ縮小設定画面へ遷移します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/b01c0dfb-1907-89ca-0038-b5866d235937.png)


サイズを"100%"から任意の数値（私は"1%以下にすることが多いです")へ変更し、赤いマークが出ていたら画面左上の"Repair"で対応（赤いマークが消えることもある）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/8a735313-c081-158d-b49c-a20925a50daf.png)


Topo-JSON形式にして"Export"します。

画面右上の"Export"を選択し、表示されたダイアログで"Topo-JSON"を選択し"Export"ボタンを押下するとjsonファイルがダウンロードされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/f1d1daa6-bffc-661e-d178-70402841147d.png)



## 3. データ準備（オプション)

Power BI で表示するデータを準備します。

市区町村名と数値データが入っているものであれば既存データを使ってもOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/ea416d81-6f9e-cada-87c1-8965a3f20d30.png)

私は公開されている埼玉県推計人口データを利用して作成しました。

https://www.pref.saitama.lg.jp/a0206/03suikei/index.html

Power BI Desktopで"空のクエリ"を作成してPower Query の詳細エディタにて以下のコードと差し替えると同じデータ構造になるかと思います（ご活用は自己責任でお願いします）。
```
let
    ソース = Excel.Workbook(Web.Contents("https://www.pref.saitama.lg.jp/documents/9099/gaiyour0509.xlsx"), null, false),
    令和5年9月1日_sheet = ソース{[Item="令和5年9月1日",Kind="Sheet"]}[Data],
    FilterNullAndWhitespace = each List.Select(_, each _ <> null and (not (_ is text) or Text.Trim(_) <> "")),
    削除された最初の行 = Table.Skip(令和5年9月1日_sheet, each try List.IsEmpty(List.Skip(FilterNullAndWhitespace(Record.FieldValues(_)), 2)) otherwise false),
    削除された他の列 = Table.SelectColumns(削除された最初の行, List.Select(Table.ColumnNames(削除された最初の行), each try not List.IsEmpty(FilterNullAndWhitespace(Table.Column(削除された最初の行, _))) otherwise true)),
    昇格されたヘッダー数 = Table.PromoteHeaders(削除された他の列, [PromoteAllScalars=true]),
    変更された型 = Table.TransformColumnTypes(昇格されたヘッダー数,{{"Column1", type text}, {"Column2", type text}, {"Column3", type any}, {"人口", type any}, {"Population", type any}, {"Column6", type any}, {"前月", type any}}),
    削除された列 = Table.RemoveColumns(変更された型,{"Column2", "Column3", "Population", "Column6", "前月"}),
    #"名前が変更された列 " = Table.RenameColumns(削除された列,{{"Column1", "市町村"}}),
    フィルターされた行 = Table.SelectRows(#"名前が変更された列 ", each ([人口] <> null and [人口] <> "Total" and [人口] <> "総数") and ([市町村] <> "市  計    " and [市町村] <> "総  計    " and [市町村] <> "郡  計    ")),
    変更された型1 = Table.TransformColumnTypes(フィルターされた行,{{"人口", Int64.Type}}),
    置き換えられた値 = Table.ReplaceValue(変更された型1,"蕨  市    ","蕨市",Replacer.ReplaceText,{"市町村"}),
    フィルターされた行1 = Table.SelectRows(置き換えられた値, each ([市町村] <> "さいたま市" and [市町村] <> "児玉郡    " and [市町村] <> "入間郡    " and [市町村] <> "北葛飾郡  " and [市町村] <> "北足立郡  " and [市町村] <> "南埼玉郡  " and [市町村] <> "大里郡    " and [市町村] <> "比企郡    " and [市町村] <> "秩父郡    "))
in
    フィルターされた行1
```

## 4. Power BI Desktopで”マップのシェイプ”ビジュアルを使って可視化
Topo-JSON形式にエクスポートしたマップ情報を利用するには"マップのシェイプ"ビジュアルを利用します。
Power BI Desktopで利用できるか念のため[ファイル] -> [オプション] -> [プレビュー機能]にて[図形マップのビジュアル]にチェックが入っているか確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/1986eef3-4231-470f-5575-b71a3c83d61b.png)


### 1. Power BI Desktopにて[マップのシェイプ]ビジュアルを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/ac29cbb8-b177-c302-8700-080e8a7e0803.png)


### 2. [場所]に位置情報を [色の彩度]に人口数を追加
既定でアメリカの州地図にマップされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/fd8648ce-71c3-ee75-a542-4db63abea892.png)


### 3. 地図を変更
[マップのシェイプ]の書式設定から[マップの設定]を開き[マップの種類]を[カスタムマップ]を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/c3c904e3-9624-aa2d-5367-dbdc101fc16e.png)

[マップの種類を追加する]をクリックするとダイアログが表示されるのでmapshaper よりエクスポートしたjsonファイルを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/2c964954-a4d7-2672-11a5-a7ddbcd206f0.png)


地図情報が設定した地図に変更されました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/32f7d44c-6b43-5cc1-502d-5089c6300a19.png)



# おわりに
市区町村レベルで塗分けする手法、TopoJSON形式への変更手法をざっくり紹介してきましたがいかがでしょうか？
今回は市区町村行政区分レベルでの塗分け例を紹介しましたが、国土交通省の図形情報ダウンロードページには行政区分以外の区分け情報シェイプファイルも公開されていますので皆様の用途に合わせて最適な表現を使って可視化していただければと思います。


カスタムマップを利用可能なビジュアルの詳細は以下のページに記載されていますので併せてご参照ください。
https://learn.microsoft.com/ja-jp/power-bi/visuals/desktop-shape-map


# 補足情報
Topo-JSON変換したファイルにてどういった情報がマッピングできるのか？を確認する方法を紹介します。
[書式設定]　-> [マップの設定]　-> [マップの種類のキーの表示] を選択するとマッピング可能なキー情報が確認可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851825/f7b38f05-3800-fe6f-e82e-86802aac9896.png)