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}
}
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() . |
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.
Install tidyterra from CRAN:
install.packages("tidyterra")
You can install the development version of tidyterra like so:
::install_github("dieghernan/tidyterra") remotes
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"
))
SpatRasters
This is a basic example which shows you how to manipulate and plot
SpatRaster
objects:
library(tidyterra)
library(terra)
# Temperatures
<- rast(system.file("extdata/cyl_temp.tif", package = "tidyterra"))
rastertemp
rastertemp#> class : SpatRaster
#> dimensions : 87, 118, 3 (nrow, ncol, nlyr)
#> resolution : 3881.255, 3881.255 (x, y)
#> extent : -612335.4, -154347.3, 4283018, 4620687 (xmin, xmax, ymin, ymax)
#> coord. ref. : World_Robinson
#> source : cyl_temp.tif
#> names : tavg_04, tavg_05, tavg_06
#> min values : 1.885463, 5.817587, 10.46338
#> max values : 13.283829, 16.740898, 21.11378
# 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
<- rastertemp %>%
variation mutate(diff = June - May) %>%
select(variation = diff)
# Add also a overlay of a SpatVector
<- vect(system.file("extdata/cyl.gpkg", package = "tidyterra"))
prov
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
<- rast(system.file("extdata/cyl_tile.tif", package = "tidyterra"))
rgb_tile
<- ggplot(prov) +
plot 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:
<- rast(system.file("extdata/asia.tif", package = "tidyterra"))
asia
::plot(asia) terra
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"
)#> # A SpatVector 12 x 7
#> # Geometry type: Polygons
#> # Geodetic CRS: lon/lat WGS 84 (EPSG:4326)
#> # Extent (x / y) : ([5° 44' 38.9" E / 6° 31' 41.71" E] , [49° 26' 52.11" N / 50° 10' 53.84" N])
#>
#> $ ID_1 <dbl> 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3
#> $ NAME_1 <chr> "Diekirch", "Diekirch", "Diekirch", "Diekirch", "Diekirch", "…
#> $ ID_2 <dbl> 1, 2, 3, 4, 5, 6, 7, 12, 8, 9, 10, 11
#> $ NAME_2 <chr> "Clervaux", "Diekirch", "Redange", "Vianden", "Wiltz", "Echte…
#> $ AREA <dbl> 312, 218, 259, 76, 263, 188, 129, 210, 185, 251, 237, 233
#> $ POP <int> 18081, 32543, 18664, 5163, 16735, 18899, 22366, 29828, 48187,…
#> $ pop_dens <dbl> 57.95192, 149.27982, 72.06178, 67.93421, 63.63118, 100.52660,…
Please leave your feedback or open an issue on https://github.com/dieghernan/tidyterra/issues.
Check our FAQs or open a new issue!
You can also ask in Stack Overflow using the tag [tidyterra].
tidyterra ggplot2 geoms are based on ggspatial implementation, by Dewey Dunnington and ggspatial contributors.