Applying revgeocode to a list of longitude-latitude coordinates
There are lots of things wrong here.
First, you have latitude and longitude reversed. All the locations in your dataset, as specified, are in Antarctica.
Second, revgeocode(...)
expects a numeric vector of length 2 containing the longitude and latitude in that order. You are passing a data.frame
object (this is the reason for the error), and as per (1) it's in the wrong order.
Third, revgeocode(...)
uses the google maps api, which limits you to 2500 queries a day. So if you really do have a large dataset, good luck with that.
This code works with your sample:
data <- read.csv(text="ID, Longitude, Latitude
311175, 41.298437, -72.929179
292058, 41.936943, -87.669838
12979, 37.580956, -77.471439")
library(ggmap)
result <- do.call(rbind,
lapply(1:nrow(data),
function(i)revgeocode(as.numeric(data[i,3:2]))))
data <- cbind(data,result)
data
# ID Longitude Latitude result
# 1 311175 41.29844 -72.92918 16 Church Street South, New Haven, CT 06519, USA
# 2 292058 41.93694 -87.66984 1632 West Nelson Street, Chicago, IL 60657, USA
# 3 12979 37.58096 -77.47144 2077-2199 Seddon Way, Richmond, VA 23230, USA
This extracts the zipcodes:
library(stringr)
data$zipcode <- substr(str_extract(data$result," [0-9]{5}, .+"),2,6)
data[,-4]
# ID Longitude Latitude zipcode
# 1 311175 41.29844 -72.92918 06519
# 2 292058 41.93694 -87.66984 60657
# 3 12979 37.58096 -77.47144 23230
Using revgeocode function in a FOR loop. Help required
No need to use a for-loop
here. I recommand you to use lapply
to avoid side effect, and pre-allocate problems:
locaddr <- lapply(seq(nrow(location)), function(i){
revgeocode(location[i,],
output = c("address"),
messaging = FALSE,
sensor = FALSE,
override_limit = FALSE)
})
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.
How to reverse geocode latitude and longitude from location stored in CloudKit? - Swift 3
Apple provides a method built into Core Location's CLGeocoder
class. Here are the docs. If successful the completion handler will give you access to an array of CLPlacemark
, so you can grab one of those and access whichever human-readable elements you need. The names of the variables are pretty generic to cover locations all over the world, so you'll have to dig in a bit to find exactly what you need. Check the docs on CLPlacemark
for exact details on the variables available to you. In your particular case you'll need locality
and administrativeArea
for city and state, respectively.
Usage would be something like this:
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
guard let placemarks = placemarks, let placemark = placemarks.first else { return }
if let city = placemark.locality, let state = placemark.administrativeArea {
//Set your labels or whatever
}
}
Use revgeocode on two columns in data.table
ggmap::revgeocode
requires location in longitude/latitude format to be a numeric array of length 2. suggestion is to use mapply
to concatenate the longitude and latitude into an array of length 2.
dt <- fread("
Pickup_longitude,Pickup_latitude
-73.945,40.799
-73.930,40.864
-73.944,40.696
-74.001,40.688
-73.926,40.755
-73.936,40.812
")
dt[, Address:=mapply(function(long, lat) ggmap::revgeocode(c(long, lat)),
Pickup_longitude, Pickup_latitude)]
Reverse geocoding speed
You could find a 'spatial' data source of the boroughs, then perform geometric operations to find points in polygons using the sf
library
Setting up the data
Find a spatial data source. Here is one of the neighbourhoods in geojson format
library(sf)
sf <- sf::st_read("https://raw.githubusercontent.com/blackmad/neighborhoods/master/new-york-city-boroughs.geojson")
Convert your coordinates into a sf
object. I've swapped your lat & lon column order.
latitude <- c(40.84935,40.76306,40.81423,40.63464,40.71054)
longitude <- c(-73.87119,-73.90235,-73.93443,-73.88090,-73.83765)
x = data.frame(longitude, latitude)
sf_x <- sf::st_as_sf(x, coords = c("longitude", "latitude"))
To perform spatial operations, the coordinate reference system needs to match between the two geometries
## set the cooridnate reference systesm to be the same
st_crs(sf_x) <- st_crs(sf)
use st_within
to find the polygons (neighbourhoods) each point is in
Point-in-polygon calculation
res <- st_within(sf_x, sf) ## return the indexes of sf that sf_x are within
This gives you a sparse matrix of the indexes of the polygons that each point is in
## view the results
sapply(res, function(x) as.character(sf$name[x]))
# [1] "Bronx" "Queens" "Manhattan" "Brooklyn" "Queens"
Visual
Confirm with a plot
library(googleway)
x$neighbourhood <- sapply(res, function(x) as.character(sf$name[x]))
mapKey <- "map_api_key"
google_map(key = mapKey) %>%
add_markers(data = x, info_window = "neighbourhood")
Further Reading
- Simple features vignette
Can I get place details against a coordinate for free?? Geocoding/Reverse Geocoding Api is not free?
I finally got this, this API is free and unlimited on client side application based on the user current location getting from (GeoLocation.getCurrentPosition Method).
https://www.bigdatacloud.com/geocoding-apis/free-reverse-geocode-to-city-api
Read their terms and conditions must.
How can I extract the zip code from the ggmap output?
I don't have an API key, but try something like the following:
my_func <- function(longlat, output){
list(list(list(c(vector("list", 7), list(12345L)))))
}
test %>%
rowwise() %>%
mutate(zip = list(my_func(c(pickup_longitude, pickup_latitude), output = "all"))) %>%
mutate(zip = zip[[1]][[1]],
zip = zip[[8]])
Replace my_func
with revgeocode
. You'll have to figure out exactly how to pick out the zip code from the output. But you can try something like the above.
Related Topics
Collapse Consecutive Runs of Numbers to a String of Ranges
How to Loop Through a Folder of CSV Files in R
How to Edit and Save Changes Made on Shiny Datatable Using Dt Package
How to Ddply() Without Sorting
Insert Images Using Knitr::Include_Graphics in a for Loop
R Ggplot2 Center Align a Multi-Line Title
How to Insert Pictures into Each Individual Bar in a Ggplot Graph
How to Pass Data Between Functions in a Shiny App
Associate a Color Palette with Ggplot2 Theme
What Are the Caveats of Using Source Versus Parse & Eval
R Map Switzerland According to Npa (Locality)
Importing Wikipedia Tables in R
Linear Interpolate Missing Values in Time Series
Multiply Columns in a Data Frame by a Vector
Questions About Set.Seed() in R
Find *All* Duplicated Records in Data.Table (Not All-But-One)