Open Street Map のデータ
このWebページでは、Open Street Map のデータを用いて SQLite 3 のテーブルを生成する。生成したデータは Python と matplotlib でプロットする。
★作成するSQLite 3データベース: osmdb
準備
次のコマンドを使用する
- osmosis のインストール
Ubuntuでのインストール手順:
# パッケージリストの情報を更新 sudo apt update sudo apt -y install osmosis - xalan のインストール
Ubuntuでのインストール手順:
# パッケージリストの情報を更新 sudo apt update sudo apt -y install xalan - Python のインストール
Ubuntuでのインストール手順:
# パッケージリストの情報を更新 sudo apt update sudo apt -y install python3 sudo apt -y install python3-pip sudo apt -y install python3-venv - matplotlib のインストール
Ubuntuでのインストール手順:Ubuntu 24.04 以降では、システムの Python 環境が externally-managed-environment となっており、pip3 による直接のインストールはエラーになる。Ubuntu のパッケージを使用する。
# パッケージリストの情報を更新 sudo apt update sudo apt -y install python3-matplotlib仮想環境を使用する場合は、次のように venv を作成してから pip3 でインストールする。
python3 -m venv /tmp/venv /tmp/venv/bin/pip3 install matplotlib - SQLite 3 のインストール
Ubuntuでのインストール手順:
# パッケージリストの情報を更新 sudo apt update sudo apt -y install libsqlite3-0 sudo apt -y install libsqlite3-dev sudo apt -y install sqlite3 - ImageMagick のインストール
Ubuntuでのインストール手順:作成した画像を display コマンドで表示するために使用する。
# パッケージリストの情報を更新 sudo apt update sudo apt -y install imagemagick
Open Street Map データの必要部分の切り出し
- 日本全体のデータのダウンロード
Geofabrik のダウンロードサーバから japan-latest.osm.pbf をダウンロードする。Geofabrik の .osm.bz2 形式のファイルは 2024年12月31日を最後に更新が停止しているため、.osm.pbf 形式を使用する。
cd /tmp wget https://download.geofabrik.de/asia/japan-latest.osm.pbf ls -la /tmp/japan-latest.osm.pbf - 必要部分の切り出し
緯度、経度を指定して必要部分の切り出しを行う
★bash プログラム
* japan-latest.osm.pbf は /tmp にあるものとする。
#!/bin/bash osmosis --read-pbf file=/tmp/japan-latest.osm.pbf \ --bounding-box left=130.2037 bottom=33.4308 right=130.5053 top=33.7147 \ --write-xml file=/tmp/fukuoka-city.osm osmosis --read-pbf file=/tmp/japan-latest.osm.pbf \ --bounding-box left=130.0355 bottom=33.4643 right=130.2938 top=33.6690 \ --write-xml file=/tmp/itoshima-city.osm処理には数分かかる
- XML 形式から CSV 形式への変換 (node, way, relation に関する CSV ファイル)
#!/bin/sh cat > /tmp/1.xslt <<-XSLT <?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="UTF-8" /> <xsl:template match="/osm/node"> /node, <xsl:value-of select="./@id"/>, <xsl:value-of select="./@lat"/>, <xsl:value-of select="./@lon"/>, <xsl:value-of select="./@version"/>, <xsl:value-of select="./@changeset"/>, <xsl:value-of select="./@timestamp"/> </xsl:template> <xsl:template match="/osm/way"> /way, <xsl:value-of select="./@id"/>, <xsl:value-of select="./@version"/>, <xsl:value-of select="./@changeset"/>, <xsl:value-of select="./@user"/>, <xsl:value-of select="./@uid"/>, <xsl:value-of select="./@timestamp"/> </xsl:template> <xsl:template match="/osm/relation"> /relation, <xsl:value-of select="./@id"/>, <xsl:value-of select="./@version"/>, <xsl:value-of select="./@changeset"/>, <xsl:value-of select="./@user"/>, <xsl:value-of select="./@uid"/>, <xsl:value-of select="./@timestamp"/> </xsl:template> </xsl:stylesheet> XSLT xalan -in /tmp/itoshima-city.osm -xsl /tmp/1.xslt > /tmp/itoshima-city.csv grep '^/node' /tmp/itoshima-city.csv | sed 's/^\/node, //g' > /tmp/itoshima-city_node.csv grep '^/way' /tmp/itoshima-city.csv | sed 's/^\/way, //g' > /tmp/itoshima-city_way.csv grep '^/relation' /tmp/itoshima-city.csv | sed 's/^\/relation, //g' > /tmp/itoshima-city_relation.csv xalan -in /tmp/fukuoka-city.osm -xsl /tmp/1.xslt > /tmp/fukuoka-city.csv grep '^/node' /tmp/fukuoka-city.csv | sed 's/^\/node, //g' > /tmp/fukuoka-city_node.csv grep '^/way' /tmp/fukuoka-city.csv | sed 's/^\/way, //g' > /tmp/fukuoka-city_way.csv grep '^/relation' /tmp/fukuoka-city.csv | sed 's/^\/relation, //g' > /tmp/fukuoka-city_relation.csv#!/bin/sh cat > /tmp/1.xslt <<-XSLT <?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="UTF-8" /> <xsl:template match="/osm/node/tag"> /node/tag, <xsl:value-of select="../@id"/>, <xsl:value-of select="../@lat"/>, <xsl:value-of select="../@lon"/>, <xsl:value-of select="../@version"/>, <xsl:value-of select="../@changeset"/>, <xsl:value-of select="../@timestamp"/>, <xsl:value-of select="./@k"/>, "<xsl:value-of select="./@v"/>" </xsl:template> <xsl:template match="/osm/way/nd"> /way/nd, <xsl:value-of select="../@id"/>, <xsl:value-of select="../@version"/>, <xsl:value-of select="../@changeset"/>, "<xsl:value-of select="../@user"/>", <xsl:value-of select="../@uid"/>, <xsl:value-of select="../@timestamp"/>, <xsl:value-of select="./@ref"/> </xsl:template> <xsl:template match="/osm/way/tag"> /way/tag, <xsl:value-of select="../@id"/>, <xsl:value-of select="../@version"/>, <xsl:value-of select="../@changeset"/>, "<xsl:value-of select="../@user"/>", <xsl:value-of select="../@uid"/>, <xsl:value-of select="../@timestamp"/>, <xsl:value-of select="./@k"/>, "<xsl:value-of select="./@v"/>" </xsl:template> <xsl:template match="/osm/relation/member"> /relation/member, <xsl:value-of select="../@id"/>, <xsl:value-of select="../@version"/>, <xsl:value-of select="../@changeset"/>, "<xsl:value-of select="../@user"/>", <xsl:value-of select="../@uid"/>, <xsl:value-of select="../@timestamp"/>, "<xsl:value-of select="./@type"/>", <xsl:value-of select="./@ref"/>, "<xsl:value-of select="./@role"/>" </xsl:template> <xsl:template match="/osm/relation/tag"> /relation/tag, <xsl:value-of select="../@id"/>, <xsl:value-of select="../@version"/>, <xsl:value-of select="../@changeset"/>, "<xsl:value-of select="../@user"/>", <xsl:value-of select="../@uid"/>, <xsl:value-of select="../@timestamp"/>, <xsl:value-of select="./@k"/>, "<xsl:value-of select="./@v"/>" </xsl:template> </xsl:stylesheet> XSLT xalan -in /tmp/itoshima-city.osm -xsl /tmp/1.xslt > /tmp/itoshima-city-tag.csv grep '^/node/tag' /tmp/itoshima-city-tag.csv | sed 's/^\/node\/tag, //g' > /tmp/itoshima-city_node_tag.csv grep '^/way/nd' /tmp/itoshima-city-tag.csv | sed 's/^\/way\/nd, //g' > /tmp/itoshima-city_way_nd.csv grep '^/way/tag' /tmp/itoshima-city-tag.csv | sed 's/^\/way\/tag, //g' > /tmp/itoshima-city_way_tag.csv grep '^/relation/member' /tmp/itoshima-city-tag.csv | sed 's/^\/relation\/member, //g' > /tmp/itoshima-city_relation_member.csv grep '^/relation/tag' /tmp/itoshima-city-tag.csv | sed 's/^\/relation\/tag, //g' > /tmp/itoshima-city_relation_tag.csv xalan -in /tmp/fukuoka-city.osm -xsl /tmp/1.xslt > /tmp/fukuoka-city-tag.csv grep '^/node/tag' /tmp/fukuoka-city-tag.csv | sed 's/^\/node\/tag, //g' > /tmp/fukuoka-city_node_tag.csv grep '^/way/nd' /tmp/fukuoka-city-tag.csv | sed 's/^\/way\/nd, //g' > /tmp/fukuoka-city_way_nd.csv grep '^/way/tag' /tmp/fukuoka-city-tag.csv | sed 's/^\/way\/tag, //g' > /tmp/fukuoka-city_way_tag.csv grep '^/relation/member' /tmp/fukuoka-city-tag.csv | sed 's/^\/relation\/member, //g' > /tmp/fukuoka-city_relation_member.csv grep '^/relation/tag' /tmp/fukuoka-city-tag.csv | sed 's/^\/relation\/tag, //g' > /tmp/fukuoka-city_relation_tag.csv
SQLite 3 データベースの生成
あらかじめ決めておく事項
このWebページでは、データベースの作成を行うので、作成するデータベースのデータベース論理名を決めておく。このWebページでは、次のように書く:
- データベース論理名: osmdb
使用するデータベースの名前のことを『データベース論理名』と呼ぶことにする。データベース論理名は自由に決めてよいが、半角の英数字を使い、スペースを含めない。
テーブルの作成
- テーブル定義 (osmnode, osmway, osmrelation)
★bash プログラム
#!/bin/bash rm -f /tmp/osmdb # cat >/tmp/a.$$.sql <<-SQL create table osmnode ( id integer not null, lat real not null, lon real not null, version integer not null, changeset integer, timestamp datetime ); create table osmway ( id integer not null, version integer not null, changeset integer, "user" text, uid integer, timestamp datetime ); create table osmrelation ( id integer not null, version integer not null, changeset integer, "user" text, uid integer, timestamp datetime ); SQL cat /tmp/a.$$.sql | sqlite3 /tmp/osmdb rm -f /tmp/a.$$.sql - データの作成
★bash プログラム
#!/bin/bash cat >/tmp/a.$$.sql <<-SQL .mode csv .import /tmp/itoshima-city_node.csv osmnode .import /tmp/itoshima-city_way.csv osmway .import /tmp/itoshima-city_relation.csv osmrelation .import /tmp/fukuoka-city_node.csv osmnode .import /tmp/fukuoka-city_way.csv osmway .import /tmp/fukuoka-city_relation.csv osmrelation SQL cat /tmp/a.$$.sql | sqlite3 /tmp/osmdb rm -f /tmp/a.$$.sql # echo 'select * from osmnode limit 10;' | sqlite3 /tmp/osmdb echo 'select * from osmway limit 10;' | sqlite3 /tmp/osmdb echo 'select * from osmrelation limit 10;' | sqlite3 /tmp/osmdb - プロット
★bash プログラム
#!/bin/bash cat > /tmp/a.py <<-PYTHON import sqlite3 import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt conn = sqlite3.connect("/tmp/osmdb") cur = conn.cursor() cur.execute("SELECT distinct lat, lon from osmnode;") rows = cur.fetchall() conn.close() lat = [r[0] for r in rows] lon = [r[1] for r in rows] plt.scatter(lon, lat, s=0.1) plt.xlabel("lon") plt.ylabel("lat") plt.savefig("/tmp/a.png") PYTHON python3 /tmp/a.py display /tmp/a.png - 追加テーブル定義 (nodetag, waynd, waytag, relationmember, relationtag)
★bash プログラム
#!/bin/bash cat > /tmp/a.sql <<-SQL create table nodetag ( nodeid integer not null, lat real not null, lon real not null, version integer not null, changeset integer, timestamp datetime, k text not null, v text not null ); create table waynd ( wayid integer not null, version integer not null, changeset integer, "user" text, uid integer, timestamp datetime, ref integer ); create table waytag ( wayid integer not null, version integer not null, changeset integer, "user" text, uid integer, timestamp datetime, k text not null, v text not null ); create table relationmember ( relationid integer not null, version integer not null, changeset integer, "user" text, uid integer, timestamp datetime, type text, ref integer, role text ); create table relationtag ( relationid integer not null, version integer not null, changeset integer, "user" text, uid integer, timestamp datetime, k text not null, v text not null ); SQL cat /tmp/a.sql | sqlite3 /tmp/osmdb - データの挿入
★bash プログラム
#!/bin/bash cat > /tmp/a.sql <<-SQL .mode csv .import /tmp/itoshima-city_node_tag.csv nodetag .import /tmp/itoshima-city_way_nd.csv waynd .import /tmp/itoshima-city_way_tag.csv waytag .import /tmp/itoshima-city_relation_member.csv relationmember .import /tmp/itoshima-city_relation_tag.csv relationtag .import /tmp/fukuoka-city_node_tag.csv nodetag .import /tmp/fukuoka-city_way_nd.csv waynd .import /tmp/fukuoka-city_way_tag.csv waytag .import /tmp/fukuoka-city_relation_member.csv relationmember .import /tmp/fukuoka-city_relation_tag.csv relationtag SQL cat /tmp/a.sql | sqlite3 /tmp/osmdb - プロット
★bash プログラム
#!/bin/bash cat > /tmp/a.py <<-PYTHON import sqlite3 import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt conn = sqlite3.connect("/tmp/osmdb") cur = conn.cursor() cur.execute("SELECT distinct lat, lon from nodetag;") rows = cur.fetchall() conn.close() lat = [r[0] for r in rows] lon = [r[1] for r in rows] plt.scatter(lon, lat, s=0.1) plt.xlabel("lon") plt.ylabel("lat") plt.savefig("/tmp/a.png") PYTHON python3 /tmp/a.py display /tmp/a.png