見出し画像

大容量csvを読み込んで高速で空間結合してみる

はじめに

今回は緯度経度情報をもった大容量のcsvファイルに、日本の市区町村を空間結合してみます。コーディング環境はJupyterNotebook前提で記載します。※今回の事例では緯度(35~37)/経度(136~140)の大量の赤点に対して、市区町村(灰色部分)の情報を付与したいと思います。

準備するもの

①各種ライブラリ
今回はdask_geopandasというちょっとマイナーなライブラリを使います。condaやpipで頑張って入れても良いのですが、私のPC環境ではエラーで弾かれたりして上手くいかなかったので、geospecialというオールインワンのパッケージがあるのでこれを活用するのがお勧めです。
地図系ライブラリを纏めて入れる方法(geospecial)|RYO|note

②大容量ファイル
手持ちにあればそれを使えばよいのですが、無ければダミーファイルで代用したいと思います。こちらの作り方は以下のページで紹介しています。
緯度経度情報をもったダミーファイルを作成する|RYO|note

③ポリゴンファイル

このページから市区町村の境界データをダウンロードしておいて下さい。(全国市区町村界データ | ESRIジャパン

サンプルコード

import subprocess
import dask.dataframe
import dask_geopandas
import geopandas
from dask.distributed import Client, LocalCluster
import matplotlib.pyplot as plt

geospecialがうまく入っていれば特にエラーが出ずにクリアできるかと思います。

ddf = dask.dataframe.read_csv('sample.csv',encoding="shift_jis",blocksize=2500000)

1,000万行のcsvを読み込みます。blocksizeは任意の大きさを選べます。大きすぎるとメモリ不足の可能性があるので要調整。

ddf.npartitions

何個に分割できたかが分かります。今回の結果は「183」でした。

len(ddf)

一応行数を確認しておきます。結果は「10000000」でした。

ddf = ddf.set_geometry(dask_geopandas.points_from_xy(ddf, x="経度", y="緯度", crs=6668))

読み込んだcsvに地図情報を付与します(x="経度", y="緯度")。座標系はJGD2011地理座標系とします(crs=6668)。なぜ6668を選択するかというと、次に読み込むポリゴンのcrsが6668だからです。

japan = geopandas.read_file("japan_ver84.shp")

日本地図のポリゴンを読み込みます。ちなみに"japan.crs"と打ち込むとcrs=6668であることが確認できます。

joined = dask_geopandas.sjoin(ddf, japan, predicate="within")

このコマンドで空間結合を行いますが、おそらくここでddf(大容量ファイル)とjapan(市区町村ポリゴン)のcrsが合っていないという警告が出ますが問題ないです。

警告メッセージ

なぜ問題ないかというと、実は今まで書いたコマンドはまだ実行されていない状態だからです。そもそもdask_geopandasの"dask"とは並列処理・分散処理できるライブラリのことで、今回のこの一連の処理も直列処理ではなく並列処理させることで高速化を図っています。

%%time
# computeをすることで初めて計算される
r = joined.compute()

今まで書いた記述をここではじめて実行させます。"%%time"はJupyterで使えるマジックコマンドで処理時間を計測します。1000万行の空間結合なので当然時間が掛かりますが、私のノートPC環境でもわずか42秒程度で実行できました。

%%time
r.to_csv('out_comp.csv', index=False, encoding="shift_jis")

ちなみにcsv出力させると、7分掛かってしまいました。実用的かどうかは微妙なところですね。

import pyogrio
pyogrio.write_dataframe(r, "joined.geojson", driver="GeoJSON")

余談ですが、pyogrioを使ってGeoJSONで出力したら5分程度でした。csvのファイルサイズは約1.5GBに対してGeoJSONは約4.0GBだったので、データの大きさを考慮しても、pyogrioというライブラリはかなり速そうです。

この記事が気に入ったらサポートをしてみませんか?