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
Rbindlist Two Data.Tables Where One Has Factor and Other Has Character Type for a Column
Determine Season from Date Using Lubridate in R
Create and Call Linear Models from List
Error: Maximal Number of Dlls Reached
Separate a Column into 2 Columns at the Last Underscore in R
Filled.Contour in R 3.0.X Throws Error
How to Remove Nas with the Tidyr::Unite Function
How to Split Column into Two in R Using Separate
How to Create Group Indices for Nested Groups in R
How to Transpose a Tibble() in R
Can You Pass a Vector to a Vararg: Vector to Sprintf
Remove Weekend Data in a Dataframe
How to Plot Pie Charts in Haplonet Haplotype Networks {Pegas}
Cannot Export Data to a File in R (Write.Csv)
"Could Not Find Function" in Roxygen Examples During Cmd Check