先日の記事では世界の国単位での地図をYellowfinで作成しましたが、そうなると次は国内の地図が欲しくなるところです。さっそくやってみましょう。
なお、手順はどうでもいいからデータがほしいというお急ぎの方は、こちらへ飛んでください。
日本の行政区域データの入手
国土交通省の国土数値情報ダウンロードサイトで公開されている行政区域データを利用します。
日本全体の地図が作りたいので、都道府県に別れたファイルではなく、全国の最新のもの(記事公開時点では平成31年)を選択してダウンロードします。
QGISでシェープファイルをCSVにエクスポートしてみる
先日の記事の手順に沿って、ダウンロードしたシェープファイルをQGISでCSVエクスポートすれば、簡単にYellowfinで使えるデータが手に入ります。
ただ、このデータは行政区域単位のポリゴンなので 一般的な業務用途には細かすぎる というデメリットがあります。
実際にYellowfinでこのデータを使ってみると、以下のように市区町村レベルや都道府県レベルで表示したい場面でも細かく分かれてしまい、期待した仕上がりにならないことがあります。
これでは使い勝手が悪いので、行政区域で分かれたポリゴンを結合して、都道府県や市区町村の単位のポリゴンデータを作りたいと思います。
PostGISの環境構築
ポリゴンを結合する方法はいろいろありますが、今回はPostGISというPostgreSQLの拡張を使います。
既存の環境を汚したくないので、Dockerを使って新規に環境構築します。
Dockerのインストール
Dockerを使うのがはじめての場合は、とりあえずDocker Desktopをインストールしておけばいいでしょう。
Dockerイメージの取得
Docker Hubで公開されているpostgis/postgisのイメージを使います。
この記事の公開時点では 15-3.3 が最新だったのですが、後述の docker compose
での起動がうまくいかなかったので、今回は 14-3.3 を使うことにしました。
以下のコマンドをシェル(Windowsならコマンドプロンプト、Macならターミナル)で実行してイメージを取得します。
$ docker pull postgis/postgis:14-3.3
docker-compose.ymlの作成
どこか任意のディレクトリに、以下のような内容の docker-compose.yml
ファイルを作成します。
version: '3'
services:
pg:
container_name: postgis_container
image: postgis/postgis:14-3.3
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
ports:
- 15432:5432
volumes:
- pg_data:/var/lib/postgresql/data
volumes:
pg_data:
driver: local
PostGISコンテナの起動
docker-compose.yml
を保存したディレクトリに移動して、以下のコマンドを実行します。
$ docker compose up -d
正常にコンテナが起動したら、Dockerのログに以下のようなメッセージが出ます。なお、ログはdocker logs --tail postgis_container
等のコマンドで確認できます。
2023-07-03 02:52:00.237 UTC [1] LOG: database system is ready to accept connections
PostGISが起動したら、docker-compose.yml
で指定したユーザー名/パスワード/ポート番号に対して接続すれば普通のPostgreSQLと同じように使えます。
試しにpgAdmin4で接続してみると以下のような感じです。
上記の docker-compose.yml
ではローカルホスト側のポート番号を 15432
に、Dockerコンテナ内のポート番号を 5432
にしていますので、YellowfinやpgAdminなどのツールからは 15432
に対して接続しにいくことになります。
ちなみにコンテナを停止するときは以下のコマンドです。
$ docker stop postgis_container (←docker-compose.ymlで設定したコンテナ名)
データの結合
構築したPostGISを使って、行政区域データから都道府県単位と市区町村単位に結合したデータをそれぞれ作ります。
シェープファイルをPostGISへインポート
まずはシェープファイルをPostGISへインポートします。
インポートする方法としてshp2psql
というPostGIS付属のコマンドを使う例がよく紹介されていますが、QGISで画面から簡単に行うこともできますので、今回はその方法を採用します。
シェープファイルの読み込み
ダウンロードした国土数値情報の.shp
ファイルをQGISにドラッグ&ドロップすると、シェープファイルが読み込まれます。
PostGISへの接続
左ペインのブラウザ
からPostgreSQL
を右クリックし、接続の新規作成
を選択します。
レイヤのインポート
メニューのデータベース
からDBマネージャー
を起動し、PostGISのデータベースを選択してレイヤ/ファイルのインポート
をクリックします。
OK
をクリックするとしばらくフリーズしたような状態になりますが、私の環境では2分間くらい待つとインポートが完了しました。
都道府県・市区町村単位のデータ結合
pgAdminで確認すると、以下のようにきちんとテーブルが作成されています。
今回はPostGISで結合の処理を行うので、pgAdmin等を使って以下のSQLを実行します。
SQLで都道府県のポリゴンを結合
CREATE TABLE public."N03_pref" (
n03_001 character varying(10) PRIMARY KEY,
geom geometry(MULTIPOLYGON, 3857) NOT NULL
);
INSERT INTO public."N03_pref"
SELECT n03_001, ST_Multi(ST_Union(ST_SetSRID(geom, 3857)))
FROM public."N03-19_190101"
WHERE n03_001 IS NOT NULL
GROUP BY n03_001;
SQLで市区町村のポリゴンを結合
CREATE TABLE public."N03_city" (
n03_007 character varying(5) PRIMARY KEY,
geom geometry(MULTIPOLYGON, 3857) NOT NULL
);
INSERT INTO public."N03_city"
SELECT n03_007, ST_Multi(ST_Union(ST_SetSRID(geom, 3857)))
FROM public."N03-19_190101"
WHERE n03_007 IS NOT NULL
GROUP BY n03_007;
結合時の注意点
上記では都道府県はn03_001(都道府県名)
を、市区町村はn03_007(行政区域コード)
を集約のキーにしています。
市区町村のキーをn03_004(市区町村名)
にしなかったのは、重複の可能性があるからです。
また、利便性を考えると、都道府県を表す2桁のコードをここで生成しておくのがいいかもしれません。
データの簡素化
QGISのメニューからレイヤ
>データソースマネージャ
を選択し、PostgreSQLの中にある先ほど作成した都道府県のテーブルを選択して追加
をクリックします。
結合したデータの問題点
Yellowfinからこのテーブルを直接参照することもできますし、先日の記事の内容に沿ってCSVにエクスポートすることも可能です。
しかしこのデータには詳細すぎて重いという欠点があります。
たとえば東京湾を拡大してみると、以下のように細部まで形状がわかります。
ですが、正直なところ都道府県レベルでここまで詳細な形状は必要ありません。
むしろ描画の処理が重くなり、場合によってはOutOfMemoryなどのシステムエラーの原因になってしまいます。
そこで、簡素化というポリゴンの頂点を間引いてデータを軽くする処理を施していきます。
QGISでジオメトリを簡素化
QGISのメニューからベクタ
>ジオメトリツール
>ジオメトリを簡素化
と進みます。
簡素化のパラメーターを設定します。
許容範囲
の値が小さくなると精度が高まり、ポリゴンの頂点が多くなって、データとしては重くなります。今回、都道府県の場合は0.01
にしました。
簡素化されたレイヤを確認すると、きちんと都道府県の形を保って表示されています。
このレイヤをまたPostgreSQLへインポートするか、CSVにエクスポートすればYellowfinで使える都道府県ポリゴンのデータになります。
市区町村についても同様の操作で簡素化すればOKですが、許容範囲は0.001
くらいに細かくするのがいいでしょう。
ここまでの手順で、Yellowfinの地図で都道府県や市区町村のポリゴンが使えるようになりました。
簡素化したデータの問題点
上記の手順で簡素化した都道府県のレイヤを拡大してみると、領域間に隙間や重なりが生じています。
ですが、Yellowfinで地図を描画する程度なら支障ないレベルだと思われるので、今回はこの問題を無視します。
この問題を解消するにはPostGISでトポロジやトポジオメトリというものを駆使する必要があるらしいのですが、この記事ではキーワードを紹介するだけにとどめ、また別の機会に検証したいと思います。
Yellowfinで今すぐ活用できるデータ
ここまでの手順をそっくりそのまま真似していただければ、Yellowfinで使えるポリゴンデータが手に入るわけですが、そもそも作業するのが面倒だという方もいらっしゃるでしょうから、作成したデータをダウンロードできるようにしておきます。
なお、データ内容は記事執筆時点(2023年7月)のものです。
都道府県・市区町村ポリゴンのCSVファイル
上記の手順で作成したCSVファイルを以下に置いています。
- 都道府県: https://github.com/hadatuna/yfgis/raw/main/n03_pref.zip
- 市区町村: https://github.com/hadatuna/yfgis/raw/main/n03_city.zip
さらに細かな町丁目レベルのデータが必要な場合は、お手数ですがこの手順に沿ってご自身で作成してください。(ファイルサイズが大きくなりすぎてGitHubには置けませんでした…)
行政区域コードのExcelファイル
ポリゴンと紐付けるために必要な都道府県や市区町村の名称及びコードの情報は、国土数値情報のサイトからダウンロード可能です。
参考情報
PostGIS環境構築
行政区域データのインポート
- 日本の行政区域データをPostgreSQLにインポートするメモ
- 国土交通省のGISデータをBigQueryにポリゴンとしてデータ投入する
- 国土数値情報のデータをQGISで表示する手順を画像で解説:無料でGISを使ってみる
- シェープファイルのデータをインポートしてみよう コマンドライン編
都道府県・市区町村のポリゴンデータ作成
- 国土数値情報のデータから都道府県ポリゴンを作る
- 国土数値情報から行政区界を作成する
- QGIS – 簡素化
- トポジオメトリを使うと隙間や重なりの無いポリゴン簡略化が比較的簡単にできる
- トポジオメトリで属性を持つ
- トポロジできれいな簡略化をやってみよう