rreverse-geocodingmapplygeonames

Reverse geocode search (country names) for many locations, output to dataframe issues when country is missing


I am using the geonames package in R to do a reverse geocode search (GNcountryCode) to find the nearest country to my inputs. My inputs are not very precise and are located in water near land. geonames allows for a search within a buffer (km) of the input location.

I was trying to use mapply to expedite retrieving country names from a long list of input locations. However, the limits on buffer size still leave some input locations without a country. To permit mapply to continue running I used tryCatch to prevent mapply from stopping.

However, this results in a non-list entry ("Error") in the overall list of lists (output below). As such, when trying to use data.table::rbindlist I get the following error: "Item n of list input is not a data.frame, data.table or list"

How can I otherwise loop or vectorize GNcountryCode to get the nearest country name to the input location and then add this name back (cbind) to the original data frame (with the understanding that some locations will not be matched to a country)?

library(geonames)# requires a username for some functionality

Latitude <- c("32.75", "33.75", "33.75", "34.25", "34.25", "36.75")
Longitude <- c("-17.25", "-52.25", "-51.75", "-52.25", "-51.75", "-25.25")
# df <- cbind.data.frame(Latitude, Longitude)

MyFun <- function(x,y) {
  MyRes <- tryCatch(GNcountryCode(lat=x, lng=y, radius=250), error = function(e) paste("Error"))
  #print(MyRes)
  return(MyRes)
}


MyResult <- mapply(MyFun, Latitude, Longitude)

data.table::rbindlist(MyResult, fill = TRUE)
#cbind(df, data.table::rbindlist(MyResult, fill = TRUE))

#Ouput
$`32.75`
$`32.75`$`languages`
[1] "pt-PT,mwl"

$`32.75`$distance
[1] "1.96436"

$`32.75`$countryCode
[1] "PT"

$`32.75`$countryName
[1] "Portuguese Republic"


$`33.75`
[1] "Error"

$`33.75`
[1] "Error"

$`34.25`
[1] "Error"

$`34.25`
[1] "Error"

$`36.75`
$`36.75`$`languages`
[1] "pt-PT,mwl"

$`36.75`$distance
[1] "22.63538"

$`36.75`$countryCode
[1] "PT"

$`36.75`$countryName
[1] "Portuguese Republic"

Solution

  • set the error parameter to return NA (and you might also want to pull out just the country name from the return of results that work)...

    library(geonames)# requires a username for some functionality
    
    Latitude <- c("32.75", "33.75", "33.75", "34.25", "34.25", "36.75")
    Longitude <- c("-17.25", "-52.25", "-51.75", "-52.25", "-51.75", "-25.25")
    df <- cbind.data.frame(Latitude, Longitude)
    
    MyFun <- function(x,y) {
      tryCatch(GNcountryCode(lat = x, lng = y, radius = 250)$countryName, error = function(e) NA_character_)
    }
    
    df$countryname <- mapply(MyFun, Latitude, Longitude)
    df
    
    #   Latitude Longitude         countryname
    # 1    32.75    -17.25 Portuguese Republic
    # 2    33.75    -52.25                <NA>
    # 3    33.75    -51.75                <NA>
    # 4    34.25    -52.25                <NA>
    # 5    34.25    -51.75                <NA>
    # 6    36.75    -25.25 Portuguese Republic