R OSRM calculate travel distance within data.frame

Viewed 50

Using the osrm package, I want to calculate the distance between two points stored in two different columns of a data frame and put it into a new column.

Doing the following, however, does not work and throws the error: object 'lon' not found. What did go wrong here?

pacman::p_load(
  tidyverse,
  sf,
  osrm
)


test_1 <- data.frame(name_1 = c("a", "b"), long = c(13.371871012201932, 13.445856720780322), lat = c(52.5212875734526, 52.503693991115206)) %>%
    st_as_sf(coords = c("long", "lat"), crs = 4326) %>%
    rename(geom_1 = "geometry")

test_2 <- data.frame(name_2 = c("c", "d"), long = c(13.401224766110927, 13.349212418670756), lat = c(52.51946945798967, 52.5149481833963)) %>%
    st_as_sf(coords = c("long", "lat"), crs = 4326) %>%
    rename(geom_2 = "geometry")

comb <- expand_grid(test_1, test_2)


routes <- comb %>%
    mutate(distances = osrmRoute(
        src = geom_1,
        dst = geom_2,
        returnclass = "sf"
    )$distance)

1 Answers

The problem is that an sf object can only have one geom column active at a time. To get around this, just call the sf objects test1 and test2 and it should work.

Please find below the modified code and the corresponding output.

  • Code
routes <- comb %>%
  mutate(distances = osrmRoute(
    src = test_1,
    dst = test_2,
    returnclass = "sf"
  )$distance)
  • Output:
routes
# A tibble: 4 x 5
  name_1              geom_1 name_2              geom_2 distances
  <chr>          <POINT [°]> <chr>          <POINT [°]>     <dbl>
1 a      (13.37187 52.52129) c      (13.40122 52.51947)      4.35
2 a      (13.37187 52.52129) d      (13.34921 52.51495)      4.35
3 b      (13.44586 52.50369) c      (13.40122 52.51947)      4.35
4 b      (13.44586 52.50369) d      (13.34921 52.51495)      4.35

Alternatively, you can specify which geom column is active in your sf object comb and you will get the same result as above.

  • Alternative code
routes <- comb %>% mutate(distances = osrmRoute(
  src = st_sf(.,sf_column_name = "geom_1"),
  dst = st_sf(.,sf_column_name = "geom_2"),
  returnclass = "sf"
)$distance)

EDIT

As a follow-up to the exchanges I had with @Jindra Lacko (cf. comments below), I propose a computeDistances() function which can help you to get what you wish. Please find below the code of the function along with its output using your object comb

  • Code of the function computeDistances
computeDistances <- function(x){  
  
  distances <- data.frame(Distances = numeric())
  
  for (i in seq(x)){
    distances[i,"Distances"]  <- osrmRoute(
      src = st_sf(x,sf_column_name = "geom_1")[i,],
      dst = st_sf(x,sf_column_name = "geom_2")[i,],
      returnclass = "sf"
    )$distance
  }
  
  results <- st_sf(cbind(x, distances))
  
  return(results)
}
  • Test of the function using your comb object
computeDistances(comb)

Simple feature collection with 4 features and 3 fields
Active geometry column: geom_1
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 13.37187 ymin: 52.50369 xmax: 13.44586 ymax: 52.52129
Geodetic CRS:  WGS 84
  name_1 name_2 Distances                    geom_1                    geom_2
1      a      c    4.3543 POINT (13.37187 52.52129) POINT (13.40122 52.51947)
2      a      d    2.6576 POINT (13.37187 52.52129) POINT (13.34921 52.51495)
3      b      c    4.4650 POINT (13.44586 52.50369) POINT (13.40122 52.51947)
4      b      d    8.1611 POINT (13.44586 52.50369) POINT (13.34921 52.51495)
Related