sf vignette のより良いバージョンは、以下をご覧ください。 https://r-spatial.github.io/sf/articles/
この vignette は、ファイルやデータベースからシンプルフィーチャをRで読み込む方法と、他の形式(テキスト、sp)に変換する方法について説明しています。
Geospatial Data Abstraction Library (GDAL) は、空間データのための スイスアーミーナイフです。実質的にあらゆるファイルフォーマットやデータベースから、 ベクトルやラスタデータを読み書きすることができます。パッケージ sf
では、関数 st_read
と st_write
によって GDAL を使用して読み書きが行われます。
GDAL が使用するデータモデルには以下のようなものがあります。
これは複雑に聞こえるかもしれませんが、200以上のデータフォーマットにマッピングするために必要なことなのです。パッケージ sf
は、可能な限りこれを単純化しようと努めていますが (例えば、1つのファイルが1つのレイヤを含むなど)、この vignette では、オプションについて説明しようと思います。
例として、sf
パッケージに同梱されている North Carolina counties SIDS dataset を読み込んでみます。
library(sf)
## Linking to GEOS 3.10.3, GDAL 3.5.1, PROJ 7.2.1; sf_use_s2() is TRUE
<- system.file("shape/nc.shp", package="sf")
fname
fname## [1] "/Users/baba/Library/R/x86_64/4.2/library/sf/shape/nc.shp"
<- st_read(fname)
nc ## Reading layer `nc' from data source
## `/Users/baba/Library/R/x86_64/4.2/library/sf/shape/nc.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 100 features and 14 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965
## Geodetic CRS: NAD27
一般的には、fname
にパス付きのファイル名を使うか、setwd()
で R の作業ディレクトリを設定してから、パスなしのファイル名を使うでしょう。
ここでは、1つの引数でデータソースとレイヤの両方を検索していることがわかります。これは、データソースに含まれるレイヤが1つの場合に機能します。レイヤの数がゼロの場合(例えば、テーブルのないデータベース)、エラーメッセージが表示されます。レイヤが複数ある場合は、最初のレイヤが返されますが、メッセージと警告が表示されます。
> st_read("PG:dbname=postgis")
in data source PG:dbname=postgis, reading layer `meuse'.
Multiple layers are present Use `st_layers' to list all layer names and their type in a data source.
Set the `layer' argument in `st_read' to read a particular layer.
Reading layer `meuse' from data source `PG:dbname=postgis' using driver `PostgreSQL'
Simple feature collection with 155 features and 12 fields
geometry type: POINT
dimension: XY
bbox: xmin: 178605 ymin: 329714 xmax: 181390 ymax: 333611
epsg (SRID): 28992
proj4string: +proj=sterea +lat_0=52.15616055555555 ...
Warning message:
In eval(substitute(expr), envir, enclos) :
automatically selected the first layer in a data source containing more than one.
このメッセージは st_layers
コマンドを指しており、データソースのドライバとレイヤをリストアップしています。
> st_layers("PG:dbname=postgis")
: PostgreSQL
Driver:
Available layers
layer_name geometry_type features fields1 meuse Point 155 12
2 meuse_sf Point 155 12
3 sids Multi Polygon 100 14
4 meuse_tbl Point 155 13
5 meuse_tbl2 Point 155 13
>
特定のレイヤを読み取ることができるようになります。
st_read("PG:dbname=postgis", "sids")
st_layers
には、フィーチャの数が足りない場合に備えて、フィーチャの数をカウントするオプションがあります。GDAL では、1 つのフィーチャレイヤに対して複数のジオメトリカラムを指定することができます。
レイヤがジオメトリのみを含み、属性 (フィールド) を含まない場合でも、st_read
はジオメトリカラムのみを含む sf
オブジェクトを返します。
GDAL はデータソースのドライバ(ファイルフォーマット)を順番に試して、自動的に検出していることがわかります。
st_read
は、表形式のデータを data.frame
に読み込むのと同じように、ベースとなる R の規則に従っています。つまり、文字データはデフォルトで factor
として読み込まれる。 文字データを文字ベクトルとして読み込むことにこだわる人のために、 stringsAsFactors
という引数を FALSE
に設定することができます。
st_read(fname, stringsAsFactors = FALSE)
あるいは、ユーザーがグローバルオプション stringsAsFactors
を設定することで、同じ効果を得ることができます。
options(stringsAsFactors = FALSE)
st_read(fname)
## Reading layer `nc' from data source
## `/Users/baba/Library/R/x86_64/4.2/library/sf/shape/nc.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 100 features and 14 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965
## Geodetic CRS: NAD27
シンプルフィーチャオブジェクトをファイルに書き込むには、少なくとも2つの引数、オブジェクトとファイル名が必要です。
st_write(nc, "nc1.shp")
ファイル名はデータソース名として扱われます。レイヤ名のデフォルトは、データソース名のベースネーム(パスを含まないファイル名)です。このため、st_write
はドライバを推測する必要があります。上記のコマンドは、例えば、次のように等価です。
st_write(nc, dsn = "nc1.shp", layer = "nc.shp", driver = "ESRI Shapefile")
## Writing layer `nc' to data source `nc1.shp' using driver `ESRI Shapefile'
## Writing 100 features with 14 fields and geometry type Multi Polygon.
ドライバーの推測の仕組みについては、次章で説明します。
出力ドライバは、データソースの拡張子 (.shp
: ESRI Shapefile
) やプレフィックス (PG:
: PostgreSQL
) から推測されます。拡張子とそれに対応するドライバ (短いドライバ名) の一覧は以下の通りです。
extension | driver short name |
---|---|
bna |
BNA |
csv |
CSV |
e00 |
AVCE00 |
gdb |
FileGDB |
geojson |
GeoJSON |
gml |
GML |
gmt |
GMT |
gpkg |
GPKG |
gps |
GPSBabel |
gtm |
GPSTrackMaker |
gxt |
Geoconcept |
jml |
JML |
map |
WAsP |
mdb |
Geomedia |
nc |
netCDF |
ods |
ODS |
osm |
OSM |
pbf |
OSM |
shp |
ESRI Shapefile |
sqlite |
SQLite |
vdv |
VDV |
xls |
xls |
xlsx |
XLSX |
The list with prefixes is:
prefix | driver short name |
---|---|
couchdb: |
CouchDB |
DB2ODBC: |
DB2ODBC |
DODS: |
DODS |
GFT: |
GFT |
MSSQL: |
MSSQLSpatial |
MySQL: |
MySQL |
OCI: |
OCI |
ODBC: |
ODBC |
PG: |
PostgreSQL |
SDE: |
SDE |
例えば、データベース内に既にテーブルが存在する場合、ドライバはどのような処理を行うか、テーブルにレコードを追加するか、上書きするかなど、様々なGDALドライバは読み書きの処理に影響するオプションを持っています。
st_write(st_as_sf(meuse), "PG:dbname=postgis", "meuse",
layer_options = "OVERWRITE=true")
テーブルが存在し、オプションが指定されていない場合、ドライバはエラーを出します。ドライバ固有のオプションは、gdal のドライバマニュアルに記載されています。 オプションは options
に複数の文字列で指定することができます。
st_read
では options
のみですが、 st_write
では dataset_options
と layer_options
を区別する必要があり、前者はデータセットのオープンに関連し、後者はデータセット内にレイヤを作成することに関連します。
パッケージ sf
は DBI
インターフェイスを使用して、空間データベースからの読み込みと書き込みをサポートします。これまでのところ、主に PostGIS
を使ってテストを行っています。他のデータベースでも動作するかもしれませんが、もっと作業が必要かもしれません。読み込みの例としては
library(RPostgreSQL)
= dbConnect(PostgreSQL(), dbname = "postgis")
conn = st_read(conn, "meuse")
meuse = st_read(conn, query = "select * from meuse limit 3;")
meuse_1_3 dbDisconnect(conn)
ここでは、2番目の例でクエリが与えられていることがわかります。このクエリには空間述語が含まれており、R で巨大な空間データセットを完全にメモリに読み込むことなく作業する方法となることがあります。 同様に、以下のようにテーブルに書き込みことができます。
= dbConnect(PostgreSQL(), dbname = "postgis")
conn st_write(conn, meuse, drop = TRUE)
dbDisconnect(conn)
ここでは、デフォルトのテーブル(レイヤ)名は、オブジェクト名(meuse
)から取得されます。論理引数 binary
は、ジオメトリを書き込む際に well-known binary と well-known text のどちらを使用するかを決定します (well-known binary の方が高速でロスレスです)。
シンプルフィーチャが表示されているのは、通常、Well Known Text (wkt) です。
st_point(c(0,1))
## POINT (0 1)
st_linestring(matrix(0:9,ncol=2,byrow=TRUE))
## LINESTRING (0 1, 2 3, 4 5, 6 7, 8 9)
これらの Well Known Text 文字列は、st_as_text
を使用して明示的に作成することができます。
= st_linestring(matrix(0:9,ncol=2,byrow=TRUE))
x = st_as_text(x)
str
x## LINESTRING (0 1, 2 3, 4 5, 6 7, 8 9)
WKT からは st_as_sfc
を使って戻すことができます。
st_as_sfc(str)
## Geometry set for 1 feature
## Geometry type: LINESTRING
## Dimension: XY
## Bounding box: xmin: 0 ymin: 1 xmax: 8 ymax: 9
## CRS: NA
## LINESTRING (0 1, 2 3, 4 5, 6 7, 8 9)
Well-known binary は st_as_binary
によって、シンプルフィーチャから生成されます。
= st_linestring(matrix(0:9,ncol=2,byrow=TRUE))
x x = st_as_binary(x))
(## [1] 01 02 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f0 3f
## [26] 00 00 00 00 00 00 00 40 00 00 00 00 00 00 08 40 00 00 00 00 00 00 10 40 00
## [51] 00 00 00 00 00 14 40 00 00 00 00 00 00 18 40 00 00 00 00 00 00 1c 40 00 00
## [76] 00 00 00 00 20 40 00 00 00 00 00 00 22 40
class(x)
## [1] "raw"
st_as_binary
が返すオブジェクトはクラス WKB
で、生のベクトルを含むリストか、単一の生のベクトルのどちらかです。これらは rawToHex
を用いて、16進数の文字ベクトルに変換することができます。
rawToHex(x)
## [1] "0102000000050000000000000000000000000000000000f03f000000000000004000000000000008400000000000001040000000000000144000000000000018400000000000001c4000000000000020400000000000002240"
sf
に戻すには、 st_as_sfc
を使用します。
= st_as_binary(st_sfc(st_point(0:1), st_point(5:6)))
x st_as_sfc(x)
## Geometry set for 2 features
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: 0 ymin: 1 xmax: 5 ymax: 6
## CRS: NA
## POINT (0 1)
## POINT (5 6)
パッケージ sp
が保持する空間オブジェクトは、 st_as_sf
と st_as_sfc
によってそれぞれシンプルフィーチャオブジェクトとジオメトリに変換することができます。
methods(st_as_sf)
## [1] st_as_sf.data.frame* st_as_sf.lpp* st_as_sf.map*
## [4] st_as_sf.owin* st_as_sf.ppp* st_as_sf.ppplist*
## [7] st_as_sf.psp* st_as_sf.s2_geography* st_as_sf.sf*
## [10] st_as_sf.sfc* st_as_sf.Spatial* st_as_sf.SpatVector*
## see '?methods' for accessing help and source code
methods(st_as_sfc)
## [1] st_as_sfc.bbox* st_as_sfc.blob*
## [3] st_as_sfc.character* st_as_sfc.dimensions*
## [5] st_as_sfc.factor* st_as_sfc.list*
## [7] st_as_sfc.map* st_as_sfc.owin*
## [9] st_as_sfc.pq_geometry* st_as_sfc.psp*
## [11] st_as_sfc.raw* st_as_sfc.s2_geography*
## [13] st_as_sfc.sf* st_as_sfc.SpatialLines*
## [15] st_as_sfc.SpatialMultiPoints* st_as_sfc.SpatialPixels*
## [17] st_as_sfc.SpatialPoints* st_as_sfc.SpatialPolygons*
## [19] st_as_sfc.tess* st_as_sfc.WKB*
## see '?methods' for accessing help and source code
例を挙げると、次のようになります。
library(sp)
data(meuse)
coordinates(meuse) = ~x+y
= st_as_sf(meuse)
m.sf = par(mar=rep(0,4))
opar plot(m.sf)
## Warning: plotting the first 10 out of 12 attributes; use max.plot = 12 to plot
## all
クラス sf
または sfc
のシンプルフィーチャオブジェクトから、対応する Spatial*
オブジェクトへの変換は、 as
メソッドを使用して、 Spatial
に強制的に変換されます。
= st_sfc(st_point(c(5,5)), st_point(c(6,9)), crs = 4326)
x as(x, "Spatial")
## SpatialPoints:
## coords.x1 coords.x2
## [1,] 5 5
## [2,] 6 9
## Coordinate Reference System (CRS) arguments: +proj=longlat +datum=WGS84
## +no_defs