Getting started examples

sfarrow は、座標参照系情報を維持したまま、Parquetファイルから/への「シンプルフィーチャ」形式の空間ベクタデータの読み書きを支援するために設計されている。基本的に、このツールは、R のオブジェクトを接続しようとするものである。 sfarrow にある https://arrow.apache.org/docs/r/ オブジェクトを接続しようとしており、その内部動作のためにこれらのパッケージに依存している。

主な目的は、Parquet ファイル内の空間データの相互運用性をサポートすることである。Rオブジェクト ( sf を含む) は arrow でファイルに書き込むことができる。しかし、これらは必ずしも空間情報を保持しておらず、Pythonで読み込むことができない。sfarrow は Python GeoPandas でも使われているメタデータ形式を実装しており、ここで説明されている。 https://github.com/geopandas/geo-arrow-spec。 これらのメタデータはまだ安定していないことに注意。sfarrow は変更される可能性があることを警告している。

# install from CRAN with install.packages('sfarrow')
# or install from devtools::install_github("wcjochem/sfarrow@main)
# load the library
library(sfarrow)
library(dplyr, warn.conflicts = FALSE)

単一ファイルの読み出しと書き込み

Parquetファイル(拡張子は .parquet )は、st_read_parquet() を使って読み込むことができ、ファイルシステムを指すことができる。これにより、sf 空間データオブジェクトがメモリ上に作成され、sf からの関数を使用して通常通り使用することができる。

# read an example dataset created from Python using geopandas
world <- st_read_parquet(system.file("extdata", "world.parquet", package = "sfarrow"))

class(world)
#> [1] "sf"         "data.frame"
world
#> Simple feature collection with 177 features and 5 fields
#> Geometry type: GEOMETRY
#> Dimension:     XY
#> Bounding box:  xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513
#> Geodetic CRS:  WGS 84
#> First 10 features:
#>      pop_est     continent                     name iso_a3 gdp_md_est
#> 1     920938       Oceania                     Fiji    FJI  8.374e+03
#> 2   53950935        Africa                 Tanzania    TZA  1.506e+05
#> 3     603253        Africa                W. Sahara    ESH  9.065e+02
#> 4   35623680 North America                   Canada    CAN  1.674e+06
#> 5  326625791 North America United States of America    USA  1.856e+07
#> 6   18556698          Asia               Kazakhstan    KAZ  4.607e+05
#> 7   29748859          Asia               Uzbekistan    UZB  2.023e+05
#> 8    6909701       Oceania         Papua New Guinea    PNG  2.802e+04
#> 9  260580739          Asia                Indonesia    IDN  3.028e+06
#> 10  44293293 South America                Argentina    ARG  8.794e+05
#>                          geometry
#> 1  MULTIPOLYGON (((180 -16.067...
#> 2  POLYGON ((33.90371 -0.95, 3...
#> 3  POLYGON ((-8.66559 27.65643...
#> 4  MULTIPOLYGON (((-122.84 49,...
#> 5  MULTIPOLYGON (((-122.84 49,...
#> 6  POLYGON ((87.35997 49.21498...
#> 7  POLYGON ((55.96819 41.30864...
#> 8  MULTIPOLYGON (((141.0002 -2...
#> 9  MULTIPOLYGON (((141.0002 -2...
#> 10 MULTIPOLYGON (((-68.63401 -...
plot(sf::st_geometry(world))

同様に、sf オブジェクトから、st_write_parquet() を使用して、新しいファイルへのパスを指定して Parquet ファイルを書き込むことができる。非空間オブジェクトは sfarrow では書き込めないので、代わりに arrow を使う必要がある。

# output the file to a new location
# note the warning about possible future changes in metadata.
st_write_parquet(world, dsn = file.path(tempdir(), "new_world.parquet"))
#> Warning: This is an initial implementation of Parquet/Feather file support and
#> geo metadata. This is tracking version 0.1.0 of the metadata
#> (https://github.com/geopandas/geo-arrow-spec). This metadata
#> specification may change and does not yet make stability promises.  We
#> do not yet recommend using this in a production setting unless you are
#> able to rewrite your Parquet/Feather files.

分割されたデータセット

Parquet ファイルの読み書きも良いが、arrow の真の力は、大きなデータセットを、クエリをより速く実行するための基準に基づいて複数のファイル、つまりパーティションに分割することにある。現在 sfarrow では、マルチファイルの空間データセットに対する基本的なサポートがある。その他のデータセットクエリーオプションについては、arrow [documentation] (https://arrow.apache.org/docs/r/articles/dataset.html)を参照

データセットの問い合わせと読み込み

sfarrowarrowsdplyr インターフェースにアクセスし、パーティショニングされた Arrow データセットを探索する {#querying-and-reading-datasets -sfarrow-accesses-arrows’s-dplyr-interface-to-explore-partitioned-arrow -datasets.}

この例では、nc.shpファイルをランダムに3つのグループに分割し、さらにランダムに2つのグループに分割して作成したデータセットを使用することにする。これにより、ネストされたファイル群が作成される。

list.files(system.file("extdata", "ds", package = "sfarrow"), recursive = TRUE)
#> [1] "split1=1/split2=1/part-3.parquet" "split1=1/split2=2/part-0.parquet"
#> [3] "split1=2/split2=1/part-1.parquet" "split1=2/split2=2/part-5.parquet"
#> [5] "split1=3/split2=1/part-2.parquet" "split1=3/split2=2/part-4.parquet"

ファイルツリーは、データが変数 “split1” と “split2” によって分割されたことを示している。これはランダム分割に使用された列名である。このパーティショニングは “Hive style” にあり、パーティショニングの変数はパスの中に入っている。

まず、arrow を使ってデータセットを開く。

ds <- arrow::open_dataset(system.file("extdata", "ds", package="sfarrow"))

小さなデータセット (この例のように) の場合、ファイルセット全体を sf オブジェクトに読み込むことができる。

nc_ds <- read_sf_dataset(ds)

nc_ds
#> Simple feature collection with 100 features and 16 fields
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965
#> Geodetic CRS:  NAD27
#> First 10 features:
#>     AREA PERIMETER CNTY_ CNTY_ID     NAME  FIPS FIPSNO CRESS_ID BIR74 SID74
#> 1  0.097     1.670  1833    1833 Hertford 37091  37091       46  1452     7
#> 2  0.062     1.547  1834    1834   Camden 37029  37029       15   286     0
#> 3  0.109     1.325  1841    1841   Person 37145  37145       73  1556     4
#> 4  0.081     1.288  1880    1880  Watauga 37189  37189       95  1323     1
#> 5  0.044     1.158  1887    1887   Chowan 37041  37041       21   751     1
#> 6  0.086     1.267  1893    1893   Yadkin 37197  37197       99  1269     1
#> 7  0.170     1.680  1903    1903 Guilford 37081  37081       41 16184    23
#> 8  0.118     1.601  1946    1946  Madison 37115  37115       58   765     2
#> 9  0.134     1.755  1958    1958    Burke 37023  37023       12  3573     5
#> 10 0.116     1.664  1964    1964 McDowell 37111  37111       56  1946     5
#>    NWBIR74 BIR79 SID79 NWBIR79 split1 split2                       geometry
#> 1      954  1838     5    1237      1      1 MULTIPOLYGON (((-76.74506 3...
#> 2      115   350     2     139      1      1 MULTIPOLYGON (((-76.00897 3...
#> 3      613  1790     4     650      1      1 MULTIPOLYGON (((-78.8068 36...
#> 4       17  1775     1      33      1      1 MULTIPOLYGON (((-81.80622 3...
#> 5      368   899     1     491      1      1 MULTIPOLYGON (((-76.68874 3...
#> 6       65  1568     1      76      1      1 MULTIPOLYGON (((-80.49554 3...
#> 7     5483 20543    38    7089      1      1 MULTIPOLYGON (((-79.53782 3...
#> 8        5   926     2       3      1      1 MULTIPOLYGON (((-82.89597 3...
#> 9      326  4314    15     407      1      1 MULTIPOLYGON (((-81.81628 3...
#> 10     134  2215     5     128      1      1 MULTIPOLYGON (((-81.81628 3...

大規模なデータセットでは、クエリを実行して、パーティショニングされたレコードの縮小セットを返したい場合が多くなる。クエリを作成する最も簡単な方法は、パーティショニング (および/または他の) 変数で dplyr::filter() を使用して行をサブセットし、dplyr::select() を使用して列をサブセットすることである。read_sf_dataset()arrow_dplyr_query を使用して dplyr::collect() を呼び出し、アローテーブルを抽出して sf に処理することになる。

nc_d12 <- ds %>% 
            filter(split1 == 1, split2 == 2) %>%
            read_sf_dataset()

nc_d12
#> Simple feature collection with 20 features and 16 fields
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: -83.36472 ymin: 34.71101 xmax: -75.45698 ymax: 36.58965
#> Geodetic CRS:  NAD27
#> First 10 features:
#>     AREA PERIMETER CNTY_ CNTY_ID        NAME  FIPS FIPSNO CRESS_ID BIR74 SID74
#> 1  0.114     1.442  1825    1825        Ashe 37009  37009        5  1091     1
#> 2  0.143     1.630  1828    1828       Surry 37171  37171       86  3188     5
#> 3  0.153     2.206  1832    1832 Northampton 37131  37131       66  1421     9
#> 4  0.118     1.421  1836    1836      Warren 37185  37185       93   968     4
#> 5  0.114     1.352  1838    1838     Caswell 37033  37033       17  1035     2
#> 6  0.143     1.663  1840    1840   Granville 37077  37077       39  1671     4
#> 7  0.108     1.483  1900    1900     Forsyth 37067  37067       34 11858    10
#> 8  0.111     1.392  1904    1904    Alamance 37001  37001        1  4672    13
#> 9  0.104     1.294  1907    1907      Orange 37135  37135       68  3164     4
#> 10 0.122     1.516  1932    1932    Caldwell 37027  37027       14  3609     6
#>    NWBIR74 BIR79 SID79 NWBIR79 split1 split2                       geometry
#> 1       10  1364     0      19      1      2 MULTIPOLYGON (((-81.47276 3...
#> 2      208  3616     6     260      1      2 MULTIPOLYGON (((-80.45634 3...
#> 3     1066  1606     3    1197      1      2 MULTIPOLYGON (((-77.21767 3...
#> 4      748  1190     2     844      1      2 MULTIPOLYGON (((-78.30876 3...
#> 5      550  1253     2     597      1      2 MULTIPOLYGON (((-79.53051 3...
#> 6      930  2074     4    1058      1      2 MULTIPOLYGON (((-78.74912 3...
#> 7     3919 15704    18    5031      1      2 MULTIPOLYGON (((-80.0381 36...
#> 8     1243  5767    11    1397      1      2 MULTIPOLYGON (((-79.24619 3...
#> 9      776  4478     6    1086      1      2 MULTIPOLYGON (((-79.01814 3...
#> 10     309  4249     9     360      1      2 MULTIPOLYGON (((-81.32813 3...
plot(sf::st_geometry(nc_d12), col="grey")

select() を使用して列のサブセットのみを読み込む場合、ジオメトリ列が返されないと、sfarrow のデフォルトの動作は read_sf_dataset からのエラーを投げることである。分析にジオメトリ列が必要ない場合は、sfarrow ではなく、arrow を使用すれば十分だろう。ただし、read_sf_datasetfind_geom = TRUE を設定すると、選択した列に加え、メタデータ中の任意のジオメトリ列が読み込まれる。

# this command will throw an error
# no geometry column selected for read_sf_dataset
# nc_sub <- ds %>% 
#             select('FIPS') %>% # subset of columns
#             read_sf_dataset()

# set find_geom
nc_sub <- ds %>%
            select('FIPS') %>% # subset of columns
            read_sf_dataset(find_geom = TRUE)

nc_sub
#> Simple feature collection with 100 features and 1 field
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965
#> Geodetic CRS:  NAD27
#> First 10 features:
#>     FIPS                       geometry
#> 1  37157 MULTIPOLYGON (((-79.53051 3...
#> 2  37083 MULTIPOLYGON (((-77.33221 3...
#> 3  37127 MULTIPOLYGON (((-78.18693 3...
#> 4  37199 MULTIPOLYGON (((-82.27921 3...
#> 5  37147 MULTIPOLYGON (((-77.47388 3...
#> 6  37101 MULTIPOLYGON (((-78.53874 3...
#> 7  37013 MULTIPOLYGON (((-77.10377 3...
#> 8  37079 MULTIPOLYGON (((-77.80518 3...
#> 9  37191 MULTIPOLYGON (((-78.16319 3...
#> 10 37123 MULTIPOLYGON (((-80.07141 3...

データセットへの書き込み

sf のオブジェクトを複数のファイルに書き込むには、再度 dplyr::group_by() を使ってクエリを構築し、パーティショニング変数を定義する。その結果は、sfarrow に渡される。

world %>%
  group_by(continent) %>%
  write_sf_dataset(file.path(tempdir(), "world_ds"), 
                   format = "parquet",
                   hive_style = FALSE)
#> Warning: This is an initial implementation of Parquet/Feather file support and
#> geo metadata. This is tracking version 0.1.0 of the metadata
#> (https://github.com/geopandas/geo-arrow-spec). This metadata
#> specification may change and does not yet make stability promises.  We
#> do not yet recommend using this in a production setting unless you are
#> able to rewrite your Parquet/Feather files.

この例では、Hive スタイルを使用していない。このため、パーティショニング変数がフォルダパスに含まれていない。

list.files(file.path(tempdir(), "world_ds"))
#> [1] "Africa"                  "Antarctica"             
#> [3] "Asia"                    "Europe"                 
#> [5] "North America"           "Oceania"                
#> [7] "Seven seas (open ocean)" "South America"

このスタイルのDatasetを読むには、開くときにパーティション変数を指定する必要がある。

arrow::open_dataset(file.path(tempdir(), "world_ds"), 
                    partitioning = "continent") %>%
  filter(continent == "Africa") %>%
  read_sf_dataset()
#> Simple feature collection with 51 features and 5 fields
#> Geometry type: GEOMETRY
#> Dimension:     XY
#> Bounding box:  xmin: -17.62504 ymin: -34.81917 xmax: 51.13387 ymax: 37.34999
#> Geodetic CRS:  WGS 84
#> First 10 features:
#>     pop_est            name iso_a3 gdp_md_est continent
#> 1  53950935        Tanzania    TZA   150600.0    Africa
#> 2    603253       W. Sahara    ESH      906.5    Africa
#> 3  83301151 Dem. Rep. Congo    COD    66010.0    Africa
#> 4   7531386         Somalia    SOM     4719.0    Africa
#> 5  47615739           Kenya    KEN   152700.0    Africa
#> 6  37345935           Sudan    SDN   176300.0    Africa
#> 7  12075985            Chad    TCD    30590.0    Africa
#> 8  54841552    South Africa    ZAF   739100.0    Africa
#> 9   1958042         Lesotho    LSO     6019.0    Africa
#> 10 13805084        Zimbabwe    ZWE    28330.0    Africa
#>                          geometry
#> 1  POLYGON ((33.90371 -0.95, 3...
#> 2  POLYGON ((-8.66559 27.65643...
#> 3  POLYGON ((29.34 -4.499983, ...
#> 4  POLYGON ((41.58513 -1.68325...
#> 5  POLYGON ((39.20222 -4.67677...
#> 6  POLYGON ((24.56737 8.229188...
#> 7  POLYGON ((23.83766 19.58047...
#> 8  POLYGON ((16.34498 -28.5767...
#> 9  POLYGON ((28.97826 -28.9556...
#> 10 POLYGON ((31.19141 -22.2515...