grass × sqlite でベクタを扱ってみる

20
GRASS×SQLite でででででででででで ででででで でででででででで でで で 2014/06/27 FOSS4G 2014 Hokkaido

Upload: yoh-fukuda

Post on 29-Jun-2015

750 views

Category:

Software


0 download

DESCRIPTION

GRASS GIS's vector attribute data can be managed by SQLite.

TRANSCRIPT

Page 1: GRASS × SQLite でベクタを扱ってみる

GRASS×SQLite でベクタを扱ってみる北海道大学 大学院環境科学院 福田 陽一朗

2014/06/27FOSS4G 2014

Hokkaido

Page 2: GRASS × SQLite でベクタを扱ってみる

私?

大学院生です。バイオマス資源の分布量の検討等をやっています。

FOSS4G を知らない頃 ...⇒GIS は高額で難しい! と思ってました。

スキャンした地図を他の地図に重ねたい!⇒ お絵かきソフトでなんちゃって幾何補正 みたいなことをして悦に入ってました

ふとしたきっかけで QGIS を知る⇒Georeferencer に衝撃を受けました。⇒ まだ日本語化の際に特殊な環境設定をしなければならない頃…

FOSS4G HKD 2012 に参加⇒ その後、 GRASS GIS を使ってエネルギーの試算などやりました。  ⇒日射量( r.sun )   小水力発電の適地検討( r.watershed etc. )

今⇒GRASS でベクタネットワーク解析などをやっています。

Page 3: GRASS × SQLite でベクタを扱ってみる

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 は各種のデータベースと接続することができます。

Page 4: GRASS × SQLite でベクタを扱ってみる

SQLite ?

・オープンソースの RDBMS (リレーショナルデータベースマネジメントシステム)

・ SQL (データベース言語)が使える!

・データベースの本体が単一の独立したファイル

・完全にローカルで動作するので、サーバーの設定が要らない。 ⇒お手軽!

こんなアプリケーションでも使われています。

http://www.sqlite.org/

Page 5: GRASS × SQLite でベクタを扱ってみる

こんな環境でやってます。

ラスタモジュール

・・・

ベクタモジュール

データベースモジュール

データの選択・抽出

データの更新

データの挿入

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 )を使ってます。

Page 6: GRASS × SQLite でベクタを扱ってみる

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

こんなファイル構造になっています。

Page 7: GRASS × SQLite でベクタを扱ってみる

こんなファイル構造になっています。

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

Page 8: GRASS × 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 コマンドを使えば、レイヤごとに別々のデータベースファイルを指定することもできます。)

現在のコネクションを表示

Page 9: GRASS × SQLite でベクタを扱ってみる

テーブルの操作

操作 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 )

Page 10: GRASS × SQLite でベクタを扱ってみる

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

Page 11: GRASS × SQLite でベクタを扱ってみる

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 を介して演算をする場合は、文字列でも数値とみなして計算しようとします。整数のみの演算の場合、整数型にも注意が必要です。

Page 12: GRASS × SQLite でベクタを扱ってみる

何ができる?

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

例)市区町村の最後の一文字でグループ化して数を集計

例)名称に「上」を含む市区町村を抽出

Page 13: GRASS × SQLite でベクタを扱ってみる

○他のテーブルとの結合( 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 には対応していないので、結合の順序に注意が必要です。

何ができる?

Page 14: GRASS × SQLite でベクタを扱ってみる

SQLite

Features 地物データ

GRASS GIS結合を利用した SELECT は、重層的に使うことができます。

何ができる?

Table CTable BTable A

Table E Table D

cat

cat

key_1 key_2

key_3

Page 15: GRASS × SQLite でベクタを扱ってみる

○選択結果の利用(サブクエリ)

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秒

何ができる?

Page 16: GRASS × SQLite でベクタを扱ってみる

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 列を更新!

地物を抽出!

直接地物の抽出ができない。。

Page 17: GRASS × SQLite でベクタを扱ってみる

ちょっと応用: 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次メッシュデータ

何ができる?

Page 18: GRASS × SQLite でベクタを扱ってみる

厄介なこと、追補・おまけ

○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 に接続し直したらすんなりできました。

Page 19: GRASS × 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 使用例を載せてくれた方々

Page 20: GRASS × SQLite でベクタを扱ってみる

ありがとうございました。ご助言、ご意見は yoh.fukuda at gmail.com

2014/06/27FOSS4G 2014

Hokkaido