return polygon nearest to a point using terra in R

Viewed 68

I am doing a point in polygon analysis

library(terra)
library(rnaturalearth)
  
crdref <- "+proj=longlat +datum=WGS84"

lonlat<- structure(c(-123.115684, -81.391114, -74.026122, -122.629252, 
                      -159.34901, 7.76101, 48.080979, 31.159987, 40.621058, 47.50331, 
                       21.978049, 36.90086), .Dim = c(6L, 2L), 
                      .Dimnames = list(NULL,c("longitude", "latitude")))

pts <- vect(lonlat, crs = crdref)
world_shp <- rnaturalearth::ne_countries()
world_shp <- terra::vect(world_shp, crs = crdref)
world_shp <- terra::project(world_shp, crdref)

plot(world_shp)
points(pts, col = "red", pch = 20)      

enter image description here

All these points lie on the edges of polygon and hence when I try to extract the the polygon under which each point lies, I get an NA

e <- terra::extract(world_shp, pts) 
e$sovereignt
NA
  

Is there any way I can return the nearest polygon for each point using the terra package

2 Answers

You can use st_join from the sf package:

library(rnaturalearth)
library(tidyverse)
library(sf)
library(rgdal)

devtools::install_github("ropensci/rnaturalearthhires")
library(rnaturalearthhires)


# create points dataframe
points <- tibble(longitude = c(123.115684, -81.391114, -74.026122, -122.629252,
                               -159.34901, 7.76101),
                 latitude = c(48.080979, 31.159987, 40.621058, 47.50331,
                              21.978049, 36.90086)) %>% 
  mutate(id = row_number())

# convert to spatial
points <- points %>% 
  st_as_sf(coords = c("longitude", "latitude"),
           crs = 4326)

# load Natural Earth data
world_shp <- rnaturalearth::ne_countries(returnclass = "sf",
                                         scale = "large")


# Plot points on top of map (just for fun)
ggplot() +
  geom_sf(data = world_shp) +
  geom_sf(data = points, color = "red", size = 2)


# check that the two objects have the same CRS
st_crs(points) == st_crs(world_shp)


# locate for each point the nearest polygon
nearest_polygon <- st_join(points, world_shp,
                           join = st_nearest_feature)

nearest_polygon

You can use terra::nearest

Example data

library(terra)
v <- vect(system.file("ex/lux.shp", package="terra"))
pts <- matrix(c(5.812,6.577,5.864,50.126,49.774,49.488), ncol=2)
pts <- vect(pts, crs = crs(w))

Solution

pv = as.points(v)
n = nearest(pts, pv)

i = pv$NAME_2[n$to_id]
i
#[1] "Clervaux"         "Echternach"       "Esch-sur-Alzette"

Illustration

plot(v, border="gray", lwd=3)
text(v, "NAME_2", cex=.6)
points(pts)
lines(pts, n, col="blue", lwd=3)
text(pts, i, cex=.6, col="red", halo=TRUE, adj=c(.5,1.5))

enter image description here

For the example above, you could also do

n = nearest(pts, v)

But in most cases you would want the distance to the border, not the centroids and do

n = nearest(pts, v, centroids=FALSE)

The current version returns the wrong IDs (for the nodes, not the polygons) so that cannot be used

Related