loop reverse_geo() function through a list

Viewed 41

Im trying to loop the reverse_geo() function from tidygeocoder package through a list.

When I apply the function to a single data frame it looks like this:

library(tidyverse, warn.conflicts = FALSE)
library(tidygeocoder)


num_coords <- 25 # number of coordinates
set.seed(103) # for reproducibility

# latitude and longitude bounds
lat_limits <- c(40.40857, 40.42585)
long_limits <- c(-3.72472, -3.66983)

# randomly sample latitudes and longitude values
random_lats <- runif(
  num_coords, 
  min = lat_limits[1], 
  max = lat_limits[2]
)

random_longs <- runif(
  num_coords, 
  min = long_limits[1], 
  max = long_limits[2]
)

# Reverse geocode the coordinates
# the speed of the query is limited to 1 coordinate per second to comply
# with Nominatim's usage policies
madrid <- reverse_geo(
  lat = random_lats, random_longs, 
  method = 'osm', full_results = TRUE,
  custom_query = list(extratags = 1, addressdetails = 1, namedetails = 1)
)

This works and returns results.

Now, when I try to apply it to each element of a list using lapply:

#NOW try to use reverse_geo() looping through a list


df1<- data.frame(random_lats,random_longs)
df2<- data.frame(random_lats,random_longs) 
list <- list(df1, df2)

data_frame_list = lapply(list, function(x) reverse_geo (lat = x[["random_lats"]], long = x[["random_longs"]], "osm", 
                                                        TRUE, list(extratags = 1, addressdetails = 1, namedetails = 1)))

I get the error: Error: limit must be NULL or >= 1. See ?reverse_geo

I think its because reverse_geo() is not correctly seeing the lat and long vectors bc Im not passing correctly into lapply().

Any recommendations on how I could fix this using lappyly or purrr::map()? I dont have a preference on using one or the other -- just want to avoid using for loop.

1 Answers

You're not having trouble with the lat or lon, what you're doing is passing in unnamed parameters to reverse_geo() that are not in the correct position. You should only pass in parameters positionally if you are certain they will be in the correct position.

You have:

data_frame_list = lapply(list, function(x) reverse_geo (
  lat = x[["random_lats"]],
  long = x[["random_longs"]],
  "osm", 
  TRUE,
  list(extratags = 1, addressdetails = 1, namedetails = 1)))

So, "osm", TRUE, and your list(...) are getting passed to the 3 arguments that follow lat and long. These are:

  1. method: which does accept "osm", so that's fine.
  2. address: name of the address column to output, which I am pretty sure you don't want to call TRUE
  3. limit: which has to be numeric, limit of results per coordinate. Yet you are passing a list(...)

Clearly, your error statement highlights the issue:

#> Error: limit must be NULL or >= 1. See ?reverse_geo

You need to explicitly pass these arguments with the name of the argument they fit. I don't know exactly which argument you wanted to pass TRUE or the list(...) to, but the code below runs.

data_frame_list = lapply(list, function(x) reverse_geo (
  lat = x[["random_lats"]],
  long = x[["random_longs"]],
  method = "osm", 
  flatten = TRUE,
  custom_query = list(extratags = 1, addressdetails = 1, namedetails = 1)))
Related