grass × sqlite でベクタを扱ってみる
DESCRIPTION
GRASS GIS's vector attribute data can be managed by SQLite.TRANSCRIPT
GRASS×SQLite でベクタを扱ってみる北海道大学 大学院環境科学院 福田 陽一朗
2014/06/27FOSS4G 2014
Hokkaido
私?
大学院生です。バイオマス資源の分布量の検討等をやっています。
FOSS4G を知らない頃 ...⇒GIS は高額で難しい! と思ってました。
スキャンした地図を他の地図に重ねたい!⇒ お絵かきソフトでなんちゃって幾何補正 みたいなことをして悦に入ってました
ふとしたきっかけで QGIS を知る⇒Georeferencer に衝撃を受けました。⇒ まだ日本語化の際に特殊な環境設定をしなければならない頃…
FOSS4G HKD 2012 に参加⇒ その後、 GRASS GIS を使ってエネルギーの試算などやりました。 ⇒日射量( r.sun ) 小水力発電の適地検討( r.watershed etc. )
今⇒GRASS でベクタネットワーク解析などをやっています。
GRASS GIS ?
・種々のラスタ解析/ベクタ解析ツールが使える! (ベクタの概念はちょっと独特)
・座標系・領域の設定あたりを乗り越えるとすごく便利!
・ QGIS の GRASS プラグイン/プロセシングからも利用できる!(ただし機能限定)
・外部から直接モジュールを介した処理が行える!( Python で)
・たまに返事をしなくなる!(大抵はこちらが悪い)
http://grass.osgeo.org/
grass: db/drivers Directory Reference http://fossies.org/dox/grass-6.4.3/dir_ef3632b5d5f243c151344966da52edc4.html
○ GRASS は各種のデータベースと接続することができます。
SQLite ?
・オープンソースの RDBMS (リレーショナルデータベースマネジメントシステム)
・ SQL (データベース言語)が使える!
・データベースの本体が単一の独立したファイル
・完全にローカルで動作するので、サーバーの設定が要らない。 ⇒お手軽!
こんなアプリケーションでも使われています。
http://www.sqlite.org/
こんな環境でやってます。
ラスタモジュール
・・・
ベクタモジュール
データベースモジュール
データの選択・抽出
データの更新
データの挿入
db.connectv.db.connectv.db.addcolv.db.renamecolv.db.dropcol
etc.
ベクタデータ
ESRI SHAPESQLite(SpatiaLite)
etc.
v.in.ogr db.in.ogr
バッチ処理には
import grass.script as grass
grass.run_command()grass.parse_command() grass.write_command()
import sqlite3
sqlite3.connect() db.execute() cursor.execute()
SELECT FROM
UPDATE SET
INSERT INTO (db.*, v.db.*)
(v.*)
(r.*)
・・・
表データcsv
テーブルの管理、 SQL による操作は管理ソフト( SQLiteSpy )を使ってます。
GRASSDatabase
Location Mapset Geometry & attribute data
/grassdata /HKD_J2K
/HKD_TKY
/HKD_J2Ku54
/sapporo
/PERMANENT
/map_1
/map_2
/cats
/cell
/cellhd
/cell_misc
/colr
/fcell
/hist
/vector
/dbf
/landuse
/cityborder
/ncensus
coor
dbin
hist
sidx
topo
・・・
/landuse.dbf
/cityborder.dbf
/ncensus.dbf
・・・
RASTER
VECTOR
こんなファイル構造になっています。
こんなファイル構造になっています。
GRASSDatabase
Location Mapset Geometry & attribute data
/grassdata /HKD_J2K
/HKD_TKY
/HKD_J2Ku54
/sapporo
/PERMANENT
/map_1
/map_2
/cats
/cell
/cellhd
/cell_misc
/colr
/fcell
/hist
/vector /landuse
/cityborder
/ncensus
coor
dbin
hist
sidx
topo
・・・
RASTER
VECTOR
/sqlite.db landuse
cityborder
ncensus
・・・
SQLite
GRASS を SQLite と接続する!
GRASS 6.4.3 (HKD_J2K)> db.connect –pdriver:dbfdatabase:'$GISDBASE/$LOCATION_NAME/$MAPSET/dbf/'schema:group:
> db.connect driver=sqlite database=$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.dbdriver:sqlitedatabase:$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.dbschema:group:
詳しくはこちら。 GRASS-SQLite driver http://grass.osgeo.org/grass64/manuals/grass-sqlite.html
http://grass.osgeo.org/grass64/manuals/db.connect.html
データベースファイル sqlite.db ⇒ ベクタデータを生成した際に自動的に生成されます
○GRASS を立ち上げて、 db.connect コマンドで接続します。
・ GRASS6 のデフォルトデータベースは DBASE ( .dbf )です。
・ database のパスはローカルのどこでも良いですが、下記がデフォルトです。
デフォルトフォルダ: $GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db
(ちなみに、 v.db.connect コマンドを使えば、レイヤごとに別々のデータベースファイルを指定することもできます。)
現在のコネクションを表示
テーブルの操作
操作 GRASS SQLite
列の追加 v.db.addcol ALTER TABLE … ADD COLUMN…
列名の変更 v.db.renamecol 非対応 *
列の削除 db.dropcol / v.db.dropcol 非対応 *
テーブル名の変更 g.rename ALTER TABLE … RENAME TO …
テーブルの削除 g.remove DROP TABLE …
* やろうと思えばできる(新テーブル作成⇒データのコピー⇒元テーブル削除⇒テーブル名の変更)
テーブルの操作は、 GRASS コマンドと SQLite ( SQL文)のどちらからでもできます。
列名の変更と列の削除は SQLite でサポートしていないので、何かと便利です。リファレンスにも書いてあります。
db.dropcol is a front-end to db.execute to allow easier usage with a special workaround for the SQLite driver to support column drop.
http://grass.osgeo.org/grass64/manuals/db.dropcol.html
GRASS で扱う上で、レイヤ名(テーブル名)や列名の制限がいくつかあります。 ・半角英数字とアンダーバーのみサポート ・最初の文字はアルファベット ・レイヤ名の字数は、 198文字までは大丈夫でした。 ・ SQL の構文で使用する語句は使用できません。 例) SELECT ・列名には大文字と小文字の区別がありません。( NAME=name )
SQLite の型
データ型 種類 GRASS の型
NULL 空文字 null
INTGER 整数( 8~ 64ビット) integer
REAL 浮動小数点数( 64ビット) double precision
TEXT テキスト型( UTF-8 / UTF-16BE / UTF-16LE ) varchar(n)
BLOB バイナリ型 -
型の名前は、一般的な名称なら理解してくれます。( INT, FLOAT, DOUBLE, VARCHAR etc. )...型の定義は GRASS に合わせるのが吉です。
SQLite に格納される値のデータ型は 5 種類。
なお、 BLOB型は GRASS GIS で扱えないので、この型の列を含むテーブルを GRASS で操作するとエラーが出ます。
GRASS 6.4.3 (HKD_J2K)> v.db.renamecol map=hoge column=old_column,new_column
WARNING: SQLite driver: unable to parse decltype: blobWARNING: SQLite driver: column 'blob', SQLite type 4 is not supported
Datatypes In SQLite Version 3 http://www.sqlite.org/datatype3.html
UPDATE hogeSET int = 0, real = 0, text = 0;
UPDATE hogeSET int = 2014/6/27, real = 2014/6/27, text = 2014/6/27;
UPDATE hogeSET int = 2014/6/27, real = 1.0*2014/6/27, text = '2014/6/27';
SQLite の型
列毎にデフォルトの型を定義することができますが、それぞれのセルには独立した型のデータを格納することができてしまいます。
一応、列の定義に応じた型で格納されていますが、、、
型ごちゃまぜでも SQLite 的には問題ありません。
SQL を介して演算をする場合は、文字列でも数値とみなして計算しようとします。整数のみの演算の場合、整数型にも注意が必要です。
何ができる?
SQL文を使って高度なデータ選択、抽出、それを元にしたデータの更新ができます。
○条件による絞込み( WHERE )
・ LIKE演算子でのパターンマッチング 例) WHERE city_name LIKE “% 上 %”
(正規表現でのマッチング( REGEXP演算子)はデフォルトでは使えない)
○データのグループ化( GROUP BY )
・同じ条件の行を一つにまとめて集計する 例) GROUP BY city_name
SELECT * FROM cityborderWHERE city_name LIKE "% 上 %"
SELECT '○○'||substr(city_name,-1) AS city_type, count(city_name) AS countFROM cityborderGROUP BY city_type
例)市区町村の最後の一文字でグループ化して数を集計
例)名称に「上」を含む市区町村を抽出
○他のテーブルとの結合( LEFT JOIN, INNER JOIN )
SELECT *FROM nationalcensus_meshLEFT JOIN landuse_meshON landuse_mesh.meshID = nationalcensus_mesh.key_code;
例)メッシュデータの結合(国勢調査と土地利用)
LEFT JOIN
国勢調査メッシュデータ 土地利用メッシュデータ
SQLite で利用できる結合は LEFT 、 INNER 、 CROSS 、 NATURAL の四種類です。 ⇒ RIGHT JOIN,FULL OUTER JOIN には対応していないので、結合の順序に注意が必要です。
何ができる?
SQLite
Features 地物データ
GRASS GIS結合を利用した SELECT は、重層的に使うことができます。
何ができる?
Table CTable BTable A
Table E Table D
cat
cat
key_1 key_2
key_3
○選択結果の利用(サブクエリ)
ALTER TABLE landuse_meshADD COLUMN Population integer; -- 列を追加UPDATE landuse_meshSET Population =(SELECT Population FROM nationalcensus_mesh WHERE landuse_mesh.meshID = nationalcensus_mesh.key_code);
例)属性データに他のテーブルのデータを挿入(データの更新: UPDATE ステートメント)
・・・
CREATE INDEX landuse_mesh_meshID ON landuse_mesh (meshID);CREATE INDEX nationalcensus_mesh_key_code ON nationalcensus_mesh (key_code);
○インデックスの設定
・ SQLite では、各カラムにインデックスを設定することができます。 これによって、結合やサブクエリを介した更新などが劇的に早くなる場合があります。
例)上記の UPDATE例の場合( landuse_mesh : 114,100 行 nationalcensus_mesh :180,222 行)
処理時間 インデックス作成前:約 2時間 15 分 ⇒インデックス作成後: 1.18秒
⇒ユニークインデックス作成( CREATE UNIQUE INDEX )後: 1.08秒
何ができる?
v.db.addcolmap=citybordercolumn="flg integer"
ちょっと応用:日本語を含むデータを扱う 例)日本語データを条件にした抽出
v.extractmap=cityborderwhere=“city_name like '%村 '”
UPDATE cityborderSET flg = 1WHERE city_name LIKE '%村 ';
v.extractmap=cityborderwhere=“flg = 1”
where条件を指定できる GRASS モジュールは多いので、重宝します。
何ができる?
flg 列を追加
SQL で flg 列を更新!
地物を抽出!
直接地物の抽出ができない。。
ちょっと応用: GROUP BY を使ってディゾルブする(4次メッシュデータ⇒3次メッシュデー
タ)
644151293
644151294
644152203
644152204
644151291
644151292
644152201
644152202
644151193
644151194
644152103
644152104
644151191
644151192
644152101
644152102
SELECT substr(meshID_4th,1,8) AS meshID_3rd, sum(Population) AS Population_3rd, sum(Household) AS Household_3rdFROM census_4thmethGROUP BY meshID_3rd;
64415129 64415220
64415119 64415210
3次メッシュの地物データは別途用意ということで…( ^^;
あとは、 meshID_3rd をキーにして地物データにJOIN
大量のデータを含む属性を条件にしたディゾルブの場合は、テーブルと地物を別立てで扱うのは良い方法かも。
4次メッシュデータ
3次メッシュデータ
何ができる?
厄介なこと、追補・おまけ
○cat 列 ・ GRASS ベクタ地物と属性データを接続しています。いじると結合関係がおかしくなります。 ・ cat 列には自動的にインデックスが生成されています。 たまに cat 列が生成されない場合もありますが、 v.category というモジュールで生成できます。 ⇒これがいわゆる「空間インデックス」というものなのかどうかは・・・わかりません。
○日本語(マルチバイト文字)対応 ・属性テーブル内のデータにマルチバイト文字 ⇒ OK SQLite ⇒ OK (ただし UTF-8) GRASS GIS ⇒ OK (ただし選択条件などコマンド中には使えない) ・列名にマルチバイト文字 ⇒ NG SQLite ⇒ OK GRASS GIS ⇒ NG
○トランザクション ・処理を確定(コミット)するまでは、処理実行前の状態まで戻すこと(ロールバック)ができます。 ・明示的に使うことで、データの更新等の処理が早くなることもあるそうです。(実感なし) ・しかし、 GRASS の処理では自動でコミットされてロールバックできないので、あまり恩恵はないかも。
○外部ソフトの使用 ・ GRASS内でも SQL を使用した選択( db.select )や更新( v.db.update )、その他の SQL 処理 ( db.execute )ができますが、外部アプリケーションを使用したほうが楽! ⇒ SQLiteManager 、 SQLiteSpy etc.
○もっとサブクエリ! ・ GRASS モジュールの where の部分にもサブクエリが使えます。複雑な選択条件を指定できます。 例) v.extract ... where=“cat IN (SELECT cat FROM hoge WHERE area < 1000 LIMIT 100)”
○dbf の方がいいことも・・・ ・ v.mkgrid (グリッドの生成)で多量のグリッドデータを作成するのに、どえらい時間がかかりました。 ⇒一旦 dbf で作成してから、改めて SQLite に接続し直したらすんなりできました。
これからと、まとめ
お世話になりました(なっています)
○GRASS7 では、 SQLite が標準の属性データフォーマットになります。 GRASS GIS Manual: SQL support in GRASS GIS http://grass.osgeo.org/grass70/manuals/sql.html
⇒ GRASS6 でデフォルトだった DBASE ( .dbf )は、「非推奨」に。
○さらに R との連携をやってみたい。
○まとめ ・ SQL は便利です。もっと使いこなせばきっともっと便利な予感。 ・ SQL で GRASS のベクタ機能はもっと便利になります。 ・ SQLite はサーバーがいらないので、とりあえず使ってみるのは割と楽です。 ・日本語の資料が身近にあればもっといいのに。( MySQL 、 PostgreSQL にはたくさんあるみたい。) ・ MySQL 、 PostgreSQL と較べてどうなの? ⇒わかりません。知りたい!
・ SQLite 入門 – DBOnline- http://www.dbonline.jp/sqlite/
・ Query Language Understood by SQLite ( SQLite 本家のリファレンス) http://www.sqlite.org/lang.html
・オープンソース GIS グラスアプローチ 第 3版
・ GRASS GIS 6.4.4svn Reference Manual http://grass.osgeo.org/grass64/manuals/
・その他 Google先生が案内してくれたたくさんの SQL 使用例を載せてくれた方々
ありがとうございました。ご助言、ご意見は yoh.fukuda at gmail.com
2014/06/27FOSS4G 2014
Hokkaido