tidyterra

tidyverse and ggplot2 methods for terra spatial objects

188
9
R

output: github_document

knitr::opts_knit$set(
  progress = TRUE,
  base.url = "https://raw.githubusercontent.com/dieghernan/tidyterra/main/"
)
knitr::opts_chunk$set(
  collapse = TRUE,
  tidy = "styler",
  comment = "#>",
  fig.path = "img/README-",
  warning = FALSE,
  message = FALSE,
  dev = "ragg_png",
  dpi = 300,
  out.width = "100%"
)

tidyterra

CRAN
status
CRAN
results
Downloads
DOI
R-CMD-check
R-hub
codecov
CodeFactor
r-universe
Project Status: Active -- The project has reached a stable, usable state and
is being actively
developed.
Stack Exchange
questions
Works with
terra-devel
Works with
sf-devel
Works with
ggplot2-devel
Works with dplyr and
readr-devel

The goal of tidyterra is to provide common methods of the tidyverse
packages
for objects created with the
terra package: SpatRaster and
SpatVector. It also provides geoms for plotting these objects with
ggplot2.

Please cite tidyterra as:

Hernangómez, D., (2023). Using the tidyverse with terra objects: the tidyterra
package. Journal of Open Source Software, 8(91), 5751,
https://doi.org/10.21105/joss.05751.

A BibTeX entry for LaTeX users is:

@article{Hernangómez2023,
  doi = {10.21105/joss.05751},
  url = {https://doi.org/10.21105/joss.05751},
  year = {2023},
  publisher = {The Open Journal},
  volume = {8},
  number = {91},
  pages = {5751},
  author = {Diego Hernangómez},
  title = {Using the {tidyverse} with {terra} objects: the {tidyterra} package},
  journal = {Journal of Open Source Software}
}

Overview

Full manual of the most recent release of tidyterra on CRAN is online:
https://dieghernan.github.io/tidyterra/

tidyverse methods implemented on tidyterra works differently depending
on the type of Spat* object:

  • SpatVector: the methods are implemented using terra::as.data.frame()
    coercion. Rows correspond to geometries and columns correspond to attributes
    of the geometry.

  • SpatRaster: The implementation on SpatRaster objects differs, since the
    methods could be applied to layers or to cells. tidyterra overall
    approach is to treat the layers as columns of a tibble and the cells as rows
    (i.e. select(SpatRaster, 1) would select the first layer of a
    SpatRaster).

The methods implemented return the same type of object used as input, unless the
expected behavior of the method is to return another type of object, (for
example, as_tibble() would return a tibble).

Current methods and functions provided by tidyterra are:

tidyverse method SpatVector SpatRaster
tibble::as_tibble() ✔️ ✔️
dplyr::select() ✔️ ✔️ Select layers
dplyr::mutate() ✔️ ✔️ Create /modify layers
dplyr::transmute() ✔️ ✔️
dplyr::filter() ✔️ ✔️ Modify cells values and (additionally) remove outer cells.
dplyr::slice() ✔️ ✔️ Additional methods for slicing by row and column.
dplyr::pull() ✔️ ✔️
dplyr::rename() ✔️ ✔️
dplyr::relocate() ✔️ ✔️
dplyr::distinct() ✔️
dplyr::arrange() ✔️
dplyr::glimpse() ✔️ ✔️
dplyr::inner_join() family ✔️
dplyr::summarise() ✔️
dplyr::group_by() family ✔️
dplyr::rowwise() ✔️
dplyr::count(), tally() ✔️
dplyr::bind_cols() / dplyr::bind_rows() ✔️ as bind_spat_cols() / bind_spat_rows()
tidyr::drop_na() ✔️ ✔️ Remove cell values with NA on any layer. Additionally, outer cells with NA are removed.
tidyr::replace_na() ✔️ ✔️
tidyr::fill() ✔️
tidyr::pivot_longer() ✔️
tidyr::pivot_wider() ✔️
ggplot2::autoplot() ✔️ ✔️
ggplot2::fortify() ✔️ to sf via sf::st_as_sf() To a tibble with coordinates.
ggplot2::geom_*() ✔️ geom_spatvector() ✔️ geom_spatraster() and geom_spatraster_rgb().

❗ A note on performance

tidyterra is conceived as a user-friendly wrapper of terra using the
tidyverse methods and verbs. This approach therefore has a cost in terms
of performance
.

If you are a heavy user of terra or you need to work with big raster
files
, terra is much more focused on terms of performance. When possible,
each function of tidyterra references to its equivalent on terra.

As a rule of thumb if your raster has less than 10.000.000 data slots counting
cells and layers (i.e. terra::ncell(your_rast)*terra::nlyr(your_rast) < 10e6)
you are good to go with tidyterra.

When plotting rasters, resampling is performed automatically (as terra::plot()
does, see the help page). You can adjust this with the maxcell parameter.

Installation

Install tidyterra from
CRAN:

install.packages("tidyterra")

You can install the development version of tidyterra like so:

remotes::install_github("dieghernan/tidyterra")

Alternatively, you can install tidyterra using the
r-universe:

# Enable this universe
install.packages("tidyterra", repos = c(
  "https://dieghernan.r-universe.dev",
  "https://cloud.r-project.org"
))

Example

SpatRasters

This is a basic example which shows you how to manipulate and plot SpatRaster
objects:

library(tidyterra)
library(terra)

# Temperatures
rastertemp <- rast(system.file("extdata/cyl_temp.tif", package = "tidyterra"))

rastertemp

# Rename
rastertemp <- rastertemp %>%
  rename(April = tavg_04, May = tavg_05, June = tavg_06)

# Facet all layers
library(ggplot2)

ggplot() +
  geom_spatraster(data = rastertemp) +
  facet_wrap(~lyr, ncol = 2) +
  scale_fill_whitebox_c(
    palette = "muted",
    labels = scales::label_number(suffix = "º"),
    n.breaks = 12,
    guide = guide_legend(reverse = TRUE)
  ) +
  labs(
    fill = "",
    title = "Average temperature in Castille and Leon (Spain)",
    subtitle = "Months of April, May and June"
  )

# Create maximum differences of two months
variation <- rastertemp %>%
  mutate(diff = June - May) %>%
  select(variation = diff)

# Add also a overlay of a SpatVector
prov <- vect(system.file("extdata/cyl.gpkg", package = "tidyterra"))

ggplot(prov) +
  geom_spatraster(data = variation) +
  geom_spatvector(fill = NA) +
  scale_fill_whitebox_c(
    palette = "deep", direction = -1,
    labels = scales::label_number(suffix = "º"),
    n.breaks = 5
  ) +
  theme_minimal() +
  coord_sf(crs = 25830) +
  labs(
    fill = "variation",
    title = "Variation of temperature in Castille and Leon (Spain)",
    subtitle = "Average temperatures in June vs. May"
  )

tidyterra also provide a geom for plotting RGB SpatRaster tiles with
ggplot2

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

plot <- ggplot(prov) +
  geom_spatraster_rgb(data = rgb_tile) +
  geom_spatvector(fill = NA) +
  theme_light()

plot

# Recognizes coord_sf()
plot +
  # Change crs and datum (for relabeling graticules)
  coord_sf(crs = 3857, datum = 3857)

tidyterra provides specific scales for plotting hypsometric maps with
ggplot2:

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

terra::plot(asia)

ggplot() +
  geom_spatraster(data = asia) +
  scale_fill_hypso_tint_c(
    palette = "gmt_globe",
    labels = scales::label_number(),
    # Further refinements
    breaks = c(-10000, -5000, 0, 2000, 5000, 8000),
    guide = guide_colorbar(reverse = TRUE)
  ) +
  labs(
    fill = "elevation (m)",
    title = "Hypsometric map of Asia"
  ) +
  theme(
    legend.position = "bottom",
    legend.title.position = "top",
    legend.key.width = rel(3),
    legend.ticks = element_line(colour = "black", linewidth = 0.3),
    legend.direction = "horizontal"
  )

SpatVectors

This is a basic example which shows you how to manipulate and plot SpatVector
objects:

vect(system.file("ex/lux.shp", package = "terra")) %>%
  mutate(pop_dens = POP / AREA) %>%
  glimpse() %>%
  autoplot(aes(fill = pop_dens)) +
  scale_fill_whitebox_c(palette = "pi_y_g") +
  labs(
    fill = "population per km2",
    title = "Population density of Luxembourg",
    subtitle = "By canton"
  )

I need your feedback

Please leave your feedback or open an issue on
https://github.com/dieghernan/tidyterra/issues.

Need help?

Check our FAQs or
open a new issue!

You can also ask in Stack Overflow using the tag
[tidyterra].

Acknowledgement

tidyterra ggplot2 geoms are based on
ggspatial implementation, by
Dewey Dunnington and ggspatial
contributors
.

Contributors

All contributions to this project are gratefully acknowledged using the allcontributors package following the allcontributors specification. Contributions of any kind are welcome!

Code


dieghernan

dramanica

Fan-iX

teunbrand

Issue Authors


Nowosad

schonhose

DidDrog11

sraul1

aloboa

kadyb

Shrubner

kdizzard

nipnipj

tigerwang1998

Edward62

kongdd

rhgof

pvjeetze

Yingjie4Science

mikejohnson51

danbebber

elgabbas

edzer

GuiSPinto

zzzqiii

mengjiezhang4ds

Beedmoser

claudehspencer

Maschette

frzambra

toihr

Breeze-Hu

Issue Contributors


twest820

stantis

rhijmans

HRodenhizer

Rapsodia86

rsbivand