6

I'd like to calculate the pairwise distance between two geometry columns. That is, I want to calculate the distance between several pairs of geometries without calculating the full distance matrix between every possible pair. I've come up with a way to do it with purrr::map2_dbl, but it feels messy. Is there a better approach?

library(sf)
library(purrr)
library(dplyr)

# Load sample data and project to EPSG:5070.
nc <- st_transform(crs = "+init=epsg:5070",
  st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE))

# Here's the full distance matrix. I don't want that.
nc_dist_mat <- st_distance(nc, nc)

# Define a function to calculate distances pairwise:
pairwise_distance <- purrr::partial(purrr::map2_dbl, .f = sf::st_distance)

# distance to self is always zero:
pairwise_distance(st_geometry(nc), st_geometry(nc))  
# distance to random county isn't always zero:
pairwise_distance(st_geometry(nc), st_geometry(dplyr::sample_frac(nc)))  
7

Loop over each geometry with mapply?

For any two geometry column vectors:

> set.seed(1)
> g1 = st_geometry(nc); g2= st_geometry(dplyr::sample_frac(nc)) 

> mapply(st_distance, g1, g2)
  [1] 152687.52 390721.95 105485.92 363253.27 214961.38  66748.80 309538.72
  [8]  11825.65 213627.60 273758.95 198366.26      0.00  66634.13 331566.88
 [15] 251378.71  45416.83 602878.69  76128.17 361629.19 153484.84 240215.77
 [etc, 100 elements]

I think this is essentially the same as your solution but only uses BSR (Base, Stable, R) code (except for the bit of dplyr I copied from you and the sf package of course).

Also, I've raised this as a new feature request on the sf github site.

  • 5
    That feature request is now implemented; the way to do this is now st_distance(g1, g2, by_element = TRUE). – karldw Jul 26 '17 at 16:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.