OpenStreetMap の地物のタグ情報

OpenStreetMapは内部で地物に対するタグ情報を持っているため、地図画像としてだけでなくデータベースとしての利用価値も高そうです。ここでは、PostgreSQLにインポートしたOpenStreetMapのデータを見てみます。

なお、OpenStreetMapのデータは日々更新されているため、ここに記載のデータ件数やタグ情報はあくまで現時点のものです。また、OpenStreetMapに登録されているデータは必ず正しいという保証はないため、それを承知で利用する必要があります。

PostgreSQL 上での OpenStreetMap のテーブル

OpenStreetMapデータのインポートにosm2pgsqlを使用した場合、PostgreSQL内に以下のテーブルの形でインポートされます。
今回はOpenStreetMap の日本域データをインポートでインポートした環境で行っています。

生成されるデータ

以下のテーブルで保持されるデータは、Mapnikがレンダリングを行う際に利用されます:

planet_osm_line: DBにインポート対象と指定されたすべてのWayが格納されます

planet_osm_point: DBにインポート対象と指定されたすべてのNodeが、タグ情報と共に格納されます

planet_osm_polygon: DBにインポート対象と指定されたすべてのPolygonが格納されます。リレーション情報もここで解決されるようです

planet_osm_roads: 低ズームレベルで利用される、`planet_osm_line`のサブセットを格納します。`planet_osm_line`は、広域の地図を作成するには含まれる情報が多すぎます。選択基準は、セットされるタグによってなされます(FIXME: highway? railway? other?)

JA:Osm2pgsql/schema

Intermediate tables (中間テーブル)

DBへのインポートがスリムモード(slim mode)で行われた場合、以下のテーブルが生成されるようです。これらのテーブルは、メモリの容量が少ない場合や、分単位の差分ファイルを利用する場合に必要となります。ジオメトリはOSMの形式を利用します(ノードの緯度/経度、設定された投影法(デフォルトはspherical mercator)、nodeのwayへの参照)。また、OSMフォーマットから最低限の変換のみが利用されます

planet_osm_nodes: imported nodes in raw format

planet_osm_rels: imported relations in raw format

planet_osm_ways: imported ways in raw format

JA:Osm2pgsql/schema

relsとwaysではtagsというカラムに地物のタグ情報が格納されています。ただ、データ型がテキスト配列型で{key, value, key, value, …}という内容になっているため、奇数番目がキー、偶数番目が値、さらにタグの個数がレコードごとにまちまちであることも自分で考慮してハンドリングしなければならないため扱いにくいです。
一方、point、line、polygon、roadsのtagsカラムはhstore型に整形済みのため、PostgreSQL上で扱いやすくなっています。
そこで、これらの4テーブルのtagsカラムについて、どのようなタグが存在しているのか調べてみます。

hstore型データを扱う演算子や関数は色々あり、ここでは主にskeys関数を使います。hstoreのキーを集合として返してくれます。

タグの件数

全てのレコードにタグがあるわけではなく、tagsカラムが空欄でタグが無いレコードも多いようです。
1レコードに対してタグが複数設定されているデータがあるため、重複も含めてキーをカウントするとタグは結構な数になります。
ではタグのキーは何種類あるかというと、テーブルごとに異なりますが大体1000~3000種類、4つのテーブル全体でまとめてカウントすると4504種類になります。

select
	(select count(*) from planet_osm_point) "レコード数",
	(select count(*) from planet_osm_point where tags <> '') "タグがあるレコード",
	(select count(*) from (select skeys(tags) from planet_osm_point) a) "タグのキー",
	(select count(*) from (select distinct skeys(tags) from planet_osm_point) a) "キーの種類"
テーブルレコード数タグがあるレコードタグのキーキーの種類
planet_osm_point200093985918921372342851
planet_osm_line9167560114705536001751989
planet_osm_polygon1475188369634313814332276
planet_osm_roads61117136998222456401137
select count(*) from
(
	select skeys(tags) keys from planet_osm_point
	union 
	select skeys(tags) keys from planet_osm_line
	union 
	select skeys(tags) keys from planet_osm_polygon
	union 
	select skeys(tags) keys from planet_osm_roads
) a
count
4504

よく使われているタグのキー

上位20件です。nameというのは当然ながらよく使われているようです。

select keys, count(*) cnt from 
(
	select skeys(tags) keys from planet_osm_point
) a
group by keys
order by cnt desc
planet_osm_pointplanet_osm_lineplanet_osm_polygonplanet_osm_roads
name:en192700name:ja442675building:levels217631name:en267439
name:ja143618lanes355092parking76017name:ja252585
operator86313name:en321315roof:colour72283lanes241247
crossing77660footway199670addr:city61274maxspeed95772
public_transport75492maxspeed132608name:en52031gauge71422
ele64617operator111933roof:shape48989electrified70241
bus51871gauge93791addr:quarter40704toll68930
name:ja_rm50965electrified88699area40344operator68346
brand45211voltage85926addr:province38922smoothness62988
opening_hours42989frequency80381addr:postcode37206usage59867
phone40499smoothness79041name:ja35494motorcycle58497
cuisine40115toll69703addr:neighbourhood35033motorcar58463
website36756operator:ja65519sport32860voltage58079
traffic_signals34914usage64519crop27069frequency57538
emergency34241operator:en62911addr:block_number25121operator:ja54336
addr:postcode29434motorcar60745addr:street24395operator:en48709
information28631motorcycle60530operator24264official_name46723
wikidata28307crossing56687golf22082alt_name40202
level28120official_name50126wikidata21320name:ja_rm32478
branch27246name:ja_rm45120website17822name:ko30132

日本語タグ

「~:ja」というのは日本語タグのキーのようです。125種類が存在しています。

select keys, count(*) cnt from 
(
	select skeys(tags) keys from planet_osm_point
	union all
	select skeys(tags) keys from planet_osm_line
	union all
	select skeys(tags) keys from planet_osm_polygon
	union all
	select skeys(tags) keys from planet_osm_roads
) a
where keys like '%:ja'
group by keys
order by cnt desc
name:ja874372
operator:ja124809
brand:ja20361
species:ja6699
genus:ja3690
bridge:name:ja3607
alt_name:ja2976
cuisine:ja2838
official_name:ja1377
denomination:ja1109
tunnel:name:ja921
wikipedia:ja882
old_name:ja713
name_alt:ja662
short_name:ja322
nat_name:ja313
start_date:ja180
loc_name:ja171
network:ja163
owner:ja118
tunnel:start_date:ja94
taxon:ja90
addr:ja87
religion:ja81
branch:ja81
place_name:ja72
reg_name:ja65
ref:ja59
is_in:ja54
shelter_type:ja50
description:ja49
junction:name:ja44
product:ja35
training:ja34
opening_date:ja32
addr:full:ja29
hazard_type:ja23
was:cuisine:ja16
produce:ja15
faculty:ja15
tunnel:opening_date:ja15
was:name:ja14
destination:lang:ja13
language:ja12
disused:name:ja11
addr:quarter:ja10
to:ja10
artist_name:ja10
trees:ja9
tactile_writing:braille:ja8
bridge:opening_date:ja7
crop:ja7
addr:city:ja7
addr:housename:ja7
is_in:island:ja7
denotation:ja6
speech_output:ja6
hairdresser:ja6
addr:province:ja5
website:ja5
bus_line[0]:ja5
wheelchair:description:ja5
contact:phone:ja4
phone:ja4
destination:street:lang:ja4
statue:ja4
disused:cuisine:ja4
sport:ja4
vending:ja3
beauty:ja3
FIXME:ja3
aed:location:ja3
healthcare:speciality:ja3
fixme:ja3
subject:ja3
massage:ja3
shop:ja3
addr:block_number:ja3
works:ja2
abandoned:name:ja2
alt_name_1:ja2
construction:name:ja2
craft:ja2
cuisune:ja2
doctors:ja2
enshrine:main:ja2
exit_to:ja2
local_name:ja2
name:en:ja2
name_1:ja2
url:ja2
was:note:ja2
office:ja1
menu_languages:ja1
int_name:ja1
sorting_name:ja1
int:ja1
historic:civilization:ja1
full_name:ja1
designation:ja1
stationery:ja1
demolished:tunnel:name:ja1
strat_date:ja1
demolished:name:ja1
suisine:ja1
deli:ja1
cutline:ja1
cusine:ja1
trade:ja1
traffic_signals:designation:ja1
cuisien:ja1
cuijone:ja1
clothes:ja1
bridge:reg_name:ja1
brand:short_name:ja1
addr:neighbourhood:ja1
books:language:ja1
blind:description:ja1
amenity:ja1
abandoned:note:ja1
was:operator:ja1
addr:suburb:ja1
addr:street:ja1
proposed:description:ja1
old_website:ja1

タグの値

特定のキーに対する値は、?演算子(hstoreがキーを含むかどうか)と->演算子(キーの値を取り出す)で調べられます。例えば以下のようにすると日本語の橋の名前が1475個得られ「日本には大体1475個くらい橋があるらしい」ということが分かります(冒頭で述べたとおりどれくらい正確かはさておき)。

select distinct tags->'bridge:name:ja' from planet_osm_line where tags ? 'bridge:name:ja'

コメントを残す