2

I would like to convert SpatVector objects to data frames for use in ggplot2.

pkgs <- c("geodata", "raster", "ggplot2", "tidy")
lapply(pkgs, require, character.only = TRUE)

boundary_GB <- geodata::gadm(country = "GB", path = tempdir(), resolution = 2, level = 1)

My current approach takes a long time:

boundary_GB_df <- broom::tidy(methods::as(boundary_GB, "Spatial"))

The plot:

ggplot(data = boundary_GB_df, mapping = aes(x = long, y = lat, group = group)) +
  geom_polygon(fill = NA, colour = "black")

I am not experienced with SpatVector objects, is there a faster approach?

I am aware of tidyterra package (i.e., tidyterra::geom_spatvector()).

Thanks

  • You can convert them to `sf` with `sf::st_as_sf()` and use `geom_sf()` – dieghernan Oct 04 '22 at 16:00
  • NB: technically you *can* turn your `SpatVector` geometry into a `data.frame` using `terra::geom(boundary_GB)`, but as it's a polygon this wouldn't probably be helpful, so `geom_sf` is a much better alternative if your goal is plotting. – Scransom Aug 17 '23 at 03:57

1 Answers1

3

sf objects are also data.frame and you can use a specific geom provided by ggplot2 (geom_sf()). Conversion between spatial vectors classes in R is as simple as:

# From SpatVector to sf
sf::st_as_sf(x_spatvector)

# From sf to SpatVector
terra::vect(x_sf)

# To sp, although for most uses is recommended to stick to sf
as(x_sf, "Spatial")


So if ypu only need to plot the spatial object, why not use ggplot2::geom_sf()/tidyterra::geom_spatvector()? Convert the object to data frame for plotting seems to be just going back and forth, unless you have a good reason for doing that.

See reprex:

library(geodata)
#> Loading required package: terra
#> terra 1.6.17
library(ggplot2)

boundary_GB <- geodata::gadm(country = "GB", path = tempdir(), resolution = 2, level = 1)

class(boundary_GB)
#> [1] "SpatVector"
#> attr(,"package")
#> [1] "terra"

library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1; sf_use_s2() is TRUE

boundary_GB_sf <- st_as_sf(boundary_GB)

class(boundary_GB_sf)
#> [1] "sf"         "data.frame"
# Is already a data.frame

# sf with geom_sf

ggplot(boundary_GB_sf) +
  geom_sf(fill = NA, colour = "black")



# Spatvector with tidyterra
library(tidyterra)
#> Loading required package: dplyr
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:terra':
#> 
#>     intersect, union
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
#> Loading required package: tibble
#> Loading required package: tidyr
#> 
#> Attaching package: 'tidyr'
#> The following object is masked from 'package:terra':
#> 
#>     extract

ggplot() +
  geom_spatvector(data = boundary_GB, fill = NA, colour = "black")

Created on 2022-10-05 with reprex v2.0.2

dieghernan
  • 2,690
  • 8
  • 16
  • Thanks for taking the time to provide an answer. I have now migrated to the **sf** and **terra** packages for my spatial work. `geom_sf()` and `geom_spatvector()` were the simplest solution. I would +1 but don't have the reputation. – user4846627 Oct 27 '22 at 11:09