Welcome to tidyterra

Welcome to {tidyterra}

tidyterratidyverse の共通メソッドを {terra} パッケージで作成した SpatRaster および SpatVectors オブジェクト用に追加するパッケージである。また、これらの種類のオブジェクトを {ggplot2} でプロットするための特別な関数 geom_spat*() も追加されている。

なぜ {tidyterra}?

Spat*オブジェクトは、通常のデータフレームとは異なる。 S4 object system を介して実装された別のタイプのオブジェクトで、独自の構文と計算メソッドを持ち、{terra} パッケージ上で実装されている。

これらのオブジェクトのためのtidyverseメソッド、より具体的には{dplyr}と{tidyr}メソッドを実装することによって、use*Rは、ちょうど表データを扱うように、より簡単にSpat**で作業できるようになった。

パフォーマンスに関しては、{terra}はこの種のオブジェクトのために働くためにはるかに最適化されているので、{terra}の構文を少し学ぶことも推奨される**ということに注意。{tidyterra}の各関数は、{terra}上の対応する等価物を (可能な限り) 参照する。

上級 {terra} ユーザーのためのメモ

前述の よ う に、 {tidyterra} はパフ ォーマン ス の観点か ら は最適化 さ れてい ない。 特に、filter()mutate() のメソッドで作業するときは、遅くなることがある。

経験則として、{tidyterra} は 10.000.000 スロット未満の情報を持つオブジェクトを処理できる (すなわち、terra::ncell(a_rast) * terra::nlyr(a_rast) < 10e6 )。

{tidyterra} ではじめる

{tidyterra}を{tidyverse}の追加ライブラリでロードする。

library(tidyterra)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tidyr)

現在、以下の方式が利用可能である。

tidyverse method SpatVector SpatRaster
tibble::as_tibble() ✔️ ✔️
dplyr::filter() ✔️ ✔️
dplyr::mutate() ✔️ ✔️
dplyr::pull() ✔️ ✔️
dplyr::relocate() ✔️ ✔️
dplyr::rename() ✔️ ✔️
dplyr::select() ✔️ ✔️
dplyr::slice() ✔️ ✔️
dplyr::transmute() ✔️ ✔️
tidyr::drop_na() ✔️ ✔️ (questioned)
tidyr::replace_na() ✔️ ✔️
ggplot2::autoplot() ✔️ ✔️
ggplot2::fortify() ✔️ to sf with sf::st_as_sf() ✔️ To tibble with coordinates

そのいくつかを実際に見てみよう。

library(terra)
f <- system.file("extdata/cyl_temp.tif", package = "tidyterra")

temp <- rast(f)

temp
#> class       : SpatRaster 
#> dimensions  : 89, 116, 3  (nrow, ncol, nlyr)
#> resolution  : 3856.617, 3856.617  (x, y)
#> extent      : 2893583, 3340950, 2019451, 2362690  (xmin, xmax, ymin, ymax)
#> coord. ref. : ETRS89-extended / LAEA Europe (EPSG:3035) 
#> source      : cyl_temp.tif 
#> names       :   tavg_04,   tavg_05,   tavg_06 
#> min values  :  0.565614,  4.294102,  8.817221 
#> max values  : 13.283829, 16.740898, 21.113781

mod <- temp %>%
  select(-1) %>%
  mutate(newcol = tavg_06 - tavg_05) %>%
  relocate(newcol, .before = 1) %>%
  replace_na(list(newcol = 3)) %>%
  rename(difference = newcol)

mod
#> class       : SpatRaster 
#> dimensions  : 89, 116, 3  (nrow, ncol, nlyr)
#> resolution  : 3856.617, 3856.617  (x, y)
#> extent      : 2893583, 3340950, 2019451, 2362690  (xmin, xmax, ymin, ymax)
#> coord. ref. : ETRS89-extended / LAEA Europe (EPSG:3035) 
#> sources     : memory  
#>               memory  
#>               memory  
#> names       : difference,   tavg_05,   tavg_06 
#> min values  :   2.786910,  4.294102,  8.817221 
#> max values  :   5.408157, 16.740898, 21.113781

先ほどの例でいうと

すべての処理において、SpatRaster の本質的な特性 (セル数、列数、行数、範囲、解像度、座標参照系) は変更されていない。filter() , slice() または drop_na() のような他のメソッドは、データフレームに適用されたときと同様に、これらのプロパティを変更することができる (その場合、行の数は変更される) 。

でプロットする {ggplot2}

SpatRaster

{tidyterra} は SpatRaster のためにいくつかの geom_* を提供する。SpatRaster が CRS を通知されている場合 (すなわち terra::crs(a_rast) != "" )、 geom は ggplot2::coord_sf() を使用し、他の空間レイヤへの座標調整のために再投影されることもある。


library(ggplot2)

# A faceted SpatRaster

ggplot() +
  geom_spatraster(data = temp) +
  facet_wrap(~lyr) +
  scale_fill_whitebox_c(
    palette = "muted",
    na.value = "white"
  )

plot of chunk terraplots



# Contour lines for a specific layer

f_volcano <- system.file("extdata/volcano2.tif", package = "tidyterra")
volcano2 <- rast(f_volcano)

ggplot() +
  geom_spatraster(data = volcano2) +
  geom_spatraster_contour(data = volcano2, breaks = seq(80, 200, 5)) +
  scale_fill_whitebox_c() +
  coord_sf(expand = FALSE) +
  labs(fill = "elevation")

plot of chunk terraplots



# Contour filled

ggplot() +
  geom_spatraster_contour_filled(data = volcano2) +
  scale_fill_whitebox_d(palette = "atlas") +
  labs(fill = "elevation")

plot of chunk terraplots

また、{tidyterra}では、プロットにイメージを追加するためにRGB SpatRasterをプロットすることができる。


# Read a vector

f_v <- system.file("extdata/cyl.gpkg", package = "tidyterra")
v <- vect(f_v)

# Read a tile
f_rgb <- system.file("extdata/cyl_tile.tif", package = "tidyterra")

r_rgb <- rast(f_rgb)

rgb_plot <- ggplot(v) +
  geom_spatraster_rgb(data = r_rgb) +
  geom_spatvector(fill = NA, size = 1)

rgb_plot

plot of chunk rgb

# Change CRS automatically

rgb_plot +
  coord_sf(crs = 3035)

plot of chunk rgb

{tidyterra} は、ヒプソメトリックマップや水深測定マップの作成に適したスケールを選択して提供する。


asia <- rast(system.file("extdata/asia.tif", package = "tidyterra"))

asia
#> class       : SpatRaster 
#> dimensions  : 232, 432, 1  (nrow, ncol, nlyr)
#> resolution  : 22550.66, 22512.94  (x, y)
#> extent      : 7619120, 17361007, -1304745, 3918256  (xmin, xmax, ymin, ymax)
#> coord. ref. : WGS 84 / Pseudo-Mercator (EPSG:3857) 
#> source      : asia.tif 
#> name        : file44bc291153f2 
#> min value   :        -10071.50 
#> max value   :          6064.73

ggplot() +
  geom_spatraster(data = asia) +
  scale_fill_hypso_tint_c(
    palette = "gmt_globe",
    labels = scales::label_number(),
    breaks = c(-10000, -5000, 0, 2500, 5000, 8000),
    guide = guide_colorbar(
      direction = "horizontal",
      title.position = "top",
      barwidth = 20
    )
  ) +
  labs(
    fill = "elevation (m)",
    title = "Hypsometric map of Asia"
  ) +
  theme_minimal() +
  theme(legend.position = "bottom")

plot of chunk hypso

SpatVector

{tidyterra} では、geom_spatvector() 関数を使って {ggplot2} で SpatVectors をプロットすることができる。

lux <- system.file("ex/lux.shp", package = "terra")

v_lux <- terra::vect(lux)

ggplot(v_lux) +
  geom_spatvector(aes(fill = POP)) +
  geom_spatvector_text(aes(label = NAME_2), color = "grey90") +
  scale_fill_binned(labels = scales::number_format()) +
  coord_sf(crs = 3857)

plot of chunk lux_ggplot

基礎となる実装は、変換 terra::vect()/sf::st_as_sf() ( [About SpatVectors] (#about) 参照) を利用し、レイヤーを作成するためのエンドポイントとして ggplot2::geom_sf() を使用することである。

SpatVectorsについて

SpatVectorオブジェクトはベクタデータである。これは、地理的な情報 (レストランの位置など) を持つ個々の点の集合であり、グループ化して線 (川など) を形成することもでき、これらの線が閉じた多角形 (国など) を形成する場合は空間多角形になることを意味する。

{terra}はS4システムでベクタファイルを扱うことができる。もう一つの選択肢として、同じ情報を表形式で表現する{sf}パッケージがある。このように、2つのパッケージは簡単に変換できる。

lux <- system.file("ex/lux.shp", package = "terra") %>%
  terra::vect()


terra::plot(lux, main = "SpatVector", axes = TRUE)

plot of chunk terra_sf



# To sf
sfobj <- sf::st_as_sf(lux)
head(sfobj, 3)
#> Simple feature collection with 3 features and 6 fields
#> Geometry type: POLYGON
#> Dimension:     XY
#> Bounding box:  xmin: 5.746118 ymin: 49.69933 xmax: 6.315773 ymax: 50.18162
#> Geodetic CRS:  WGS 84
#>   ID_1   NAME_1 ID_2   NAME_2 AREA   POP                       geometry
#> 1    1 Diekirch    1 Clervaux  312 18081 POLYGON ((6.026519 50.17767...
#> 2    1 Diekirch    2 Diekirch  218 32543 POLYGON ((6.178368 49.87682...
#> 3    1 Diekirch    3  Redange  259 18664 POLYGON ((5.881378 49.87015...

plot(sfobj$geometry, main = "sf", axes = TRUE)

plot of chunk terra_sf


# Back to terra

lux2 <- terra::vect(sfobj)

lux2
#>  class       : SpatVector 
#>  geometry    : polygons 
#>  dimensions  : 12, 6  (geometries, attributes)
#>  extent      : 5.74414, 6.528252, 49.44781, 50.18162  (xmin, xmax, ymin, ymax)
#>  coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#>  names       :  ID_1   NAME_1  ID_2   NAME_2  AREA   POP
#>  type        : <num>    <chr> <num>    <chr> <num> <int>
#>  values      :     1 Diekirch     1 Clervaux   312 18081
#>                    1 Diekirch     2 Diekirch   218 32543
#>                    1 Diekirch     3  Redange   259 18664

その意味で、{sf}はすでに{tidyverse}メソッドのそれ自身の実装を持っている。 SpatVectorを{sf}に変換することは情報の損失がなく簡単なので、{tidyterra}は特にSpatRastersに焦点を合わせている。terra}をどのように扱うかの例を参照。+ {sf} を使用する例を参照。+ {dplyr}での作業例を参照。

library(dplyr)
library(terra)
library(sf)

lux_summ <- lux2 %>%
  # to sf
  st_as_sf() %>%
  # dplyr
  group_by(ID_1) %>%
  summarise(TOTPOP = sum(POP)) %>%
  # back to terra
  vect()

lux_summ
#>  class       : SpatVector 
#>  geometry    : polygons 
#>  dimensions  : 3, 2  (geometries, attributes)
#>  extent      : 5.74414, 6.528252, 49.44781, 50.18162  (xmin, xmax, ymin, ymax)
#>  coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#>  names       :  ID_1 TOTPOP
#>  type        : <num>  <int>
#>  values      :     1  91186
#>                    2  71093
#>                    3 439726

terra::plot(lux_summ, "TOTPOP")

plot of chunk full_spatvector