Loop for Reverse Geocoding in R

Loop for Reverse Geocoding in R

Based on this answer, you could create new variables in your data.frame

We use mapply() to process your coordinates and return the results in a list res.

res <- mapply(FUN = function(lon, lat) { 
revgeocode(c(lon, lat), output = "more")
},
df$lon, df$lat
)

Then, we use rbindlist() from data.table to convert the list into a data.frame (with fill = TRUE since not all elements of res have the same lenghts i.e. some results do not return a street_number and a postal_code) and cbind() it to the original data

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

Update

Following up on your comment, if you want to process more than 2500 queries, you could subscribe to Google Maps APIs Premium Plan to unlock higher quotas. Then you can pass on your credentials to revgeocode() using the signature and client parameter.

As per mentionned in the documentation:

Upon purchasing your Google Maps APIs Premium Plan license, you will
receive a welcome email from Google that contains your client ID and
your private cryptographic key.

Your client ID is used to access the special features of Google Maps
APIs Premium Plan. All client IDs begin with a gme- prefix. Pass your
client ID as the value of the client parameter. A unique digital
signature is generated using your private cryptographic key. Pass this
signature as the value of the signature parameter.

You can see how it works under the hood by examining the revgeocode() source and see how the URL is constructed:

sensor4url <- paste("&sensor=", sensor, sep = "")
client4url <- paste("&client=", client, sep = "")
signature4url <- paste("&signature=", signature, sep = "")
url_string <- paste("http://maps.googleapis.com/maps/api/geocode/json?latlng=",
loc4url, sensor4url, sep = "")
if (userType == "business") {
url_string <- paste(url_string, client4url, signature4url,
sep = "")
}

Data

df <- structure(list(lat = c(32.31, 32.19, 34.75, 35.09, 35.35, 34.74 ), lon = 
c(119.827, 119.637, 119.381, 119.364, 119.534, 119.421 )), .Names =
c("lat", "lon"), row.names = c(21L, 32L, 37L, 48L, 50L, 89L), class = "data.frame")

Subscript out of bounds for reverse geocoding loop in R

I tested your code and it's working for me. But you aren't testing for status. If latlng is incorrect, it return "ZERO RESULTS" as status (and no rgc$results exist). Here's the code that I tested.

rev <- function(latlng, api_key) {

url= url(paste("https://maps.googleapis.com/maps/api/geocode/json?","latlng=",latlng,"&key=",sep=""))
rgc <- fromJSON(paste(readLines(url), collapse = ''))
close(url)

if (rgc["status"] == "OK") {
rgc <- rgc$results[[1]]
with(rgc, {
rgcdf <<- data.frame(address = formatted_address)
})
for (k in seq_along(rgc$address_components)) {
rgcdf <- cbind(rgcdf, rgc$address_components[[k]]$long_name)
}
names(rgcdf) <- c("address", sapply(rgc$address_components, function(l) l$types[1]))
rgcdf["valid_latlong"] <- TRUE
rgcdf
} else {
rgcdf <- c(valid_latlong=FALSE)
}
}

I tested this with:

rev("12.9756300,77.6066230")

Are you passing latlng in this format? Or c(9756300,77.6066230) . Then you need to do

latlng <-  gsub(' ','%20', paste(latlng, collapse=","))

Also you haven't integrated api key in the code snippet that you shared. Pass api_key to query param.

Problems with reverse geocoding loops with latitude longitude co-ordinates using googleway: r gives the same results for different co-ordinates

It looks like the calls to google_geocode can return more than one address for each lat/longitude pair thus you could be overwriting your data in the output data frame.

Also, I am not sure your if statement is evaluating properly.

Here is my attempt on your problem:

library(googleway)

origAddress<-read.table(header = TRUE, text = "lat lng
1.436316 103.8299
1.375093 103.8516
1.369347 103.8398
1.367353 103.8426")

#add the output column
origAddress$venadd<-NA

for(i in 1:nrow(origAddress))
{
# Print("Working...")
result <- google_reverse_geocode(location = c(origAddress$lat[i],origAddress$lng[i]),
key=key,
location_type = "rooftop")

#add a slight pause so not to overload the call requests
Sys.sleep(1)
if(result$status =="OK" ){
#multiple address can be returned with in gecode request picks the first one
origAddress$venadd[i] <- result$results$formatted_address[1]
#use this to collect all addresses:
#paste(result$results$formatted_address, collapse = " ")
}
}

Since the call to google_reverse_geocode returns the address, I just pull the first address from the result saving a call to the internet (performance improvement). Also since the call returns a status, I check for an OK and if exist save the first address.

Hope this helps.

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

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

How to batch reverse geocode in R?

I think you are going about this the wrong way. You can find the zip codes of lat/lon coordinates without a geocoder - all you need is to download the US zipcodes shapefile here and then do a spatial join:

library(sp)
library(rgdal)

#import zips shapefile and transform CRS
zips <- readOGR("cb_2015_us_zcta510_500k.shp")
zips <- spTransform(zips, CRS("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"))

#here is a sample with three cities in New York State and their coordinates
df <- as.data.frame(matrix(nrow = 3, ncol =3))
colnames(df) <- c("lat", "lon", "city")

df$lon <- c(43.0481, 43.1610, 42.8864)
df$lat <- c(-76.1474, -77.6109,-78.8784)
df$city <- c("Syracuse", "Rochester", "Buffalo")

df
lat lon city
1 -76.1474 43.0481 Syracuse
2 -77.6109 43.1610 Rochester
3 -78.8784 42.8864 Buffalo

#extract only the lon/lat
xy <- df[,c(1,2)]

#transform coordinates into a SpatialPointsDataFrame
spdf <- SpatialPointsDataFrame(coords = xy, data = df, proj4string = CRS("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"))

#subset only the zipcodes in which points are found
zips_subset <- zips[spdf, ]

#NOTE: the column in zips_subset containing zipcodes is ZCTA5CE10
#use over() to overlay points in polygons and then add that to the original dataframe

df$zip <- over(spdf, zips_subset[,"ZCTA5CE10"])

And voila! You have the zipcode of each point

df
lat lon city ZCTA5CE10
1 -76.1474 43.0481 Syracuse 13202
2 -77.6109 43.1610 Rochester 14604
3 -78.8784 42.8864 Buffalo 14202

Reverse Geo Coding in R

The current CRAN version of revgeo_0.15 does not have the revgeocode function. If you upgrade to this version, you'll find a revgeo function, which takes longitude, latitude arguments. Your column C should not be passed into the function.

    revgeo::revgeo(latitude=df[, 'A'], longitude=df[, 'B'], output='frame')
[1] "Getting geocode data from Photon: http://photon.komoot.de/reverse?lon=74.0314209&lat=15.3859085"
housenumber street city state zip country
1 House Number Not Found Street Not Found Borim Goa Postcode Not Found India


Related Topics



Leave a reply



Submit