rgoogle-mapsggmapreverse-geocodinggoogleway

Extract address components from coordiantes


I'm trying to reverse geocode with R. I first used ggmap but couldn't get it to work with my API key. Now I'm trying it with googleway.

newframe[,c("Front.lat","Front.long")]

  Front.lat Front.long
1 -37.82681   144.9592
2 -37.82681   145.9592

newframe$address <- apply(newframe, 1, function(x){
  google_reverse_geocode(location = as.numeric(c(x["Front.lat"], 
x["Front.long"])),
                         key = "xxxx")
})

This extracts the variables as a list but I can't figure out the structure.

I'm struggling to figure out how to extract the address components listed below as variables in newframe

postal_code, administrative_area_level_1, administrative_area_level_2, locality, route, street_number

I would prefer each address component as a separate variable.


Solution

  • After reverse geocoding into newframe$address the address components could be extracted further as follows:

    # Make a boolean array of the valid ("OK" status) responses (other statuses may be "NO_RESULTS", "REQUEST_DENIED" etc).
    sel <- sapply(c(1: nrow(newframe)), function(x){
      newframe$address[[x]]$status == 'OK'
    })
    
    # Get the address_components of the first result (i.e. best match) returned per geocoded coordinate.
    address.components <- sapply(c(1: nrow(newframe[sel,])), function(x){
      newframe$address[[x]]$results[1,]$address_components
    })
    
    # Get all possible component types.
    all.types <- unique(unlist(sapply(c(1: length(address.components)), function(x){
      unlist(lapply(address.components[[x]]$types, function(l) l[[1]]))
    })))
    
    # Get "long_name" values of the address_components for each type present (the other option is "short_name").
    all.values <- lapply(c(1: length(address.components)), function(x){
      types <- unlist(lapply(address.components[[x]]$types, function(l) l[[1]]))
      matches <- match(all.types, types)
      values <- address.components[[x]]$long_name[matches]
    })
    
    # Bind results into a dataframe.
    all.values <- do.call("rbind", all.values)
    all.values <- as.data.frame(all.values)
    names(all.values) <- all.types
    
    # Add columns and update original data frame.
    newframe[, all.types] <- NA
    newframe[sel,][, all.types] <- all.values
    

    Note that I've only kept the first type given per component, effectively skipping the "political" type as it appears in multiple components and is likely superfluous e.g. "administrative_area_level_1, political".