I wrote a very simple function (which works well) that returns the timezone given a set of coordinates:
library(XML)
findTZ <- function(lon, lat, date=Sys.Date())
{ apiurl <- sprintf("https://maps.googleapis.com/maps/api/timezone/%s?location=%s,%s×tamp=%d&sensor=%s",
"xml", lat, lon, as.numeric(as.POSIXct(date)), "false")
TZ <- xmlParse(readLines(apiurl))[["string(//time_zone_id)"]]
return(TZ)
}
findTZ(-112.86, 53.61) # example
However, when I try to run the function on a list of coordinates in a dataframe I get an error: Error in file(con, "r") : invalid 'description' argument
Any hints at what I'm getting wrong here? It seems like it should be very simple.
Here's the very basic data I'm testing on:
DF <- data.frame(
longitude = c(-122, -112, -102),
latitude = c(54, 53, 52)
)
DF$timezone = findTZ(lon=DF$longitude, lat=DF$latitude)
Thank you for any pointers!
After implementing the answer from @Floo0 I tried implementing the same solution with another function for calculating sunrise/set times using the same location data (and that I want to return in local time, hence the timezone function).
Here's the sunrise function:
library(maptools)
SSun <- function(lon, lat, date, deg=0, dir, tzone)
{ # deg = solar depth: rise/set=0, civil=6, nautical=12, astronomical=18
# dir = direction: sunrise="dawn", sunset="dusk"
# tzone = time zone of output, NOT of location
siteX <- SpatialPoints(matrix(c(lon, lat), nrow=1), proj4string=CRS("+proj=longlat +datum=WGS84"))
dateX <- as.POSIXct(date, tz=tzone)
duskX <- crepuscule(siteX, dateX, solarDep=deg, direction=dir, POSIXct.out=TRUE)
duskX <- duskX$time # keep only date and time, discard day_frac
return(duskX)
}
SSun(-112.86, 53.61, "2016-09-25", deg=0, dir="dawn", tzone="America/Edmonton") # example
And the updated timezone function:
library(tidyverse); library(xml2)
findTZ <- function(lon, lat, date=Sys.Date()){
apiurl <- sprintf("https://maps.googleapis.com/maps/api/timezone/%s?location=%s,%s×tamp=%d&sensor=%s",
"xml", lat, lon, as.numeric(as.POSIXct(date)), "false")
read_xml(apiurl) %>% xml_find_first(".//time_zone_id") %>% xml_text
}
findTZ(-112.86, 53.61) # example
And the code I used to call both functions:
DF %>% mutate(date = as.POSIXct(date),
TZ = map2_chr(longitude, latitude, findTZ),
sunrise = SSun(longitude, latitude, date, deg=0, dir="dawn", tzone=TZ))
I feel like I must be misunderstanding how this works. Any insights?
You can do the following (using xml2
instead of XML
as i find it easier to use)
require(xml2)
findTZ <- function(lon, lat, date=Sys.Date()){
apiurl <- sprintf("https://maps.googleapis.com/maps/api/timezone/%s?location=%s,%s×tamp=%d&sensor=%s",
"xml", lat, lon, as.numeric(as.POSIXct(date)), "false")
read_xml(apiurl) %>% xml_find_first(".//time_zone_id") %>% xml_text
}
To loop through your test data you can use:
require(tidyverse)
DF %>% mutate(TZ = map2_chr(longitude, latitude, findTZ))
Which gives you:
longitude latitude TZ
1 -122 54 America/Vancouver
2 -112 53 America/Edmonton
3 -102 52 America/Regina
As @Rich Scriven points out correctly you need to loop through the data somewhere. This loop is "hidden" in the map2_chr
call.
考虑mapply
将每对按元素值传递给函数以返回向量:
DF$timezones <- mapply(findTZ, DF$longitude, DF$latitude)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.