LoginSignup
6
1

More than 3 years have passed since last update.

BigQueryGISでOpenStreetMapのデータを触ってみる

Last updated at Posted at 2020-12-02

はじめに

⚠️以下の内容をお手元で試すと、BigQueryで数百円~の課金が発生します⚠️

OpenStreetMapとは

有志で作られてるオープンな地図みたいです。wikiみたいに誰でも編集追加できるようです。
地図情報は大きく三つのオブジェクトで構成されています

オブジェクト 表すもの 役割 サンプル
node 点    建物、ラベル、交差点など 東京駅
way 線(面) 建物、道、路線、境界、川などの一部 東京スカイツリー
relation 関係性 一つのnodeやwayで表せないもの 皇居

これらのオブジェクトにtagをつけることで役割を明確にしています。

このデータがBigQueryの公開データセットにて公開されています1ので、それを触っていきます。

BigQueryGIS

BigQuery上では地理データ(GEOGRAPHY型)を扱うことができます。
これにより、「ある点とある点がどれくらい離れているのか?」や「ある点から300m以内の特定の条件を満たす地点はいくつあるのか」などSQLで記述することができます。

https://cloud.google.com/bigquery/docs/reference/standard-sql/geography_functions?hl=JA
こちらにある様々な関数がSQLで使えます。

新宿区だけのデータに絞る

BigQueryに格納されているデータは全世界のデータになっており、毎回フルアクセスするとBQの料金高くなってしまいます。
ですので新宿区だけに絞ってみましょう。

OSMで検索した結果、relationのID1758858が新宿区の境界を表していることがわかりました。
ということで、これの内側のnode,way,relationだけが欲しいです。
BigQueryの公開データセットはこちらです。
こちらのplanet_nodesplanet_waysplanet_relationsがnode, way, relationに対応しています2

とりあえず、お遊び用のデータセットを作っておきます。osm_test

一旦nodeだけで絞ってみましょう。

CREATE TABLE osm_test.nodes AS
WITH area AS (
  SELECT geometry AS shinjuku
  FROM `bigquery-public-data.geo_openstreetmap.planet_relations`
  WHERE id = 1758858
)
SELECT id, all_tags, latitude, longitude
FROM `bigquery-public-data.geo_openstreetmap.planet_nodes`
CROSS JOIN area
WHERE ST_WITHIN(geometry, shinjuku)

297GB=約$1.5

これで、osm_testデータセットに新宿区だけに絞ったnodesテーブルが作成されます。
planet_nodesテーブルのgeometryカラムはなぜかnullが多いのでlatitude,longitudeをselectしています。
基本的にGISの絞り込みはCROSS JOINで結合し、WHERE句で絞り込む感じで書きます。
今回の場合は新宿のエリア内のnodeだけが欲しいのでST_WITHIN関数を使用しました。

コンビニを抽出

コンビニを示すタグのkeyとvalueの組み合わせがなんなのかOSMのwikiで調べると、
https://wiki.openstreetmap.org/wiki/JA:Tag:shop%3Dconvenience
のページが見つかります。
どうやら、keyがshopでvalueがconvenienceのものを見つければいいようです。

all_tagsから特定のtagを抽出するためにヘルパー関数を作っておくと便利

CREATE FUNCTION osm_test.get(
  key STRING, tags ARRAY<STRUCT<k STRING, v STRING>>
) AS ((
  SELECT v
  FROM UNNEST(tags)
  WHERE key = k
));

keyがshopでvalueがconvenienceを抽出するだけ!

SELECT
  id,
  osm_test.get('name', all_tags) AS name,
  ST_GEOGPOINT(longitude, latitude) AS point,
FROM osm_test.nodes
WHERE osm_test.get('shop', all_tags) = "convenience"

このままじゃよくわからないので、

BigQuery Geo Vizを使って表示してみましょう。
shijuku_convenience.png
確かに新宿区内のコンビニが取得できている気がします。


  1. 謎の更新頻度をほこっている 

  2. 他にも色々テーブルがあるようですがよくわかっていません。わかる人教えて。 

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1