I apologise in advance for this query as I assume it will be very easy to answer for most, however, I’m not well versed in R and I’m having to use it for a work project.
I have to calculate a ‘distance’ and ‘time’ between roughly 3000 postcodes via their longitude and latitude but I’m having issues setting up a data frame in R.
I have a column of longitudes and a column for latitudes for the origin postcodes and the exact same for the destination postcodes. These are all individuals and I would like to calculate their distance & time traveled.
My code:
coordinates <- data.frame(lon = c(Postcodes_Travel[["Longitude (Usual)"]],
Postcodes_Travel[["Longitude (Dest)"]]),
lat = c(Postcodes_Travel[["Latitude (Usual)"]],
Postcodes_Travel[["Latitude (Dest)"]]
))
res <- ors_matrix(coordinates, metrics = c("duration", "distance"), units = "km")
This code generates a large matrix whilst all I’m looking for is a new column with Distance and one with Time
Person A: Origin → Dest = Distance + Time
Any help with this would be greatly appreciated as I’m at a loss.
I recently made code to generate distance and time matrices between more than 5000 geographic points in R. I hope it can help you.
######################################################
library(jsonlite)
library(httr)
entremunics<-function(coordl) {
require("jsonlite")
require("httr")
coord<-coordl # coordl is coordinate matrix
# the columns must be [longitude, latitude] in that order in the array.
body<-list(locations=coord,
metrics=list("distance","duration"),
units="km")
body <- toJSON(body, auto_unbox = TRUE)
url<-'https://api.openrouteservice.org/v2/matrix/driving-car'
r <- POST(url,body = body,
add_headers(`Accept` = "application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8"),
add_headers(`Authorization`= "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"),
add_headers(`Content-Type`= "application/json; charset=utf-8"))
h<-r$content
data0<-fromJSON(rawToChar(as.raw(strtoi(h, 16L))))
data0$restantes<-as.numeric(r$headers$`x-ratelimit-remaining`) # key request limits
return(data0)
}
coords<-read.csv("geographic coordinates.csv")
coords<-coords[order(coords$cod_ibge),] # names or code of each point
distance<-diag(nrow(coords)) # identity matrix
#distance<-as.matrix(fst::read_fst("distance_km.fst")) # retrieve the matrix from where it left off
durations<-diag(nrow(coords))
#durations<-as.matrix(fst::read_fst("durations_seconds.fst")) # retrieve the matrix from where it left off
rownames(distance)<-rownames(durations)<-coords$cod_ibge
colnames(distance)<-colnames(durations)<-coords$cod_ibge
i<-seq(1,nrow(coords),by=25) # 50 geographic coordinate points is the limit of requests per matrix
j<-c(i[-1]-1,nrow(coords)) # allowing 25 fixed points of origin to 25 variant points of destination (or the opposite)
# loopin to fill the matrix
for (k1 in 1:(length(i)-1)) {
s1<-c(i[k1]:j[k1])
for (k2 in k1:(length(i)-1)) {
s2<-i[k2+1]:j[k2+1]
coordl<-as.matrix(coords[c(s1,s2),4:3]) # the columns must be [longitude, latitude] in that order in the array.
distbetween<-entremunics(coordl)
distance[c(s1,s2),c(s1,s2)]<-distbetween$distances
durations[c(s1,s2),c(s1,s2)]<-distbetween$durations
Sys.sleep(2) # pause to respect api limitations
# .3 to .8 seconds for 50 or 40 requests per minute varies with the internet speed at the time.
# I put in 2 seconds because there were often access cuts.
# Even with a key with permissions of up to 25 thousand requests a day.
if(distbetween$restantes==1){
# to meet the site's daily restrictions limit
break
}
}
# save if there is an error to not start from the beginning.
df.distance<-as.data.frame(distance)
fst::write_fst(df.distance,"distance_km.fst", compress = 0)
df.durations<-as.data.frame(durations)
fst::write_fst(df.durations,"durations_seconds.fst", compress = 0)
if(distbetween$restantes<(length(i)-k1)){
# to meet the site's daily restrictions limit
break
}
cat(k1, "-")
}
df.distance<-as.data.frame(distance)
df.distance$cod_munic<-coords$cod_ibge
fst::write_fst(df.distance,"distance_km.fst", compress = 100)
df.durations<-as.data.frame(durations)
df.durations$cod_munic<-coords$cod_ibge
fst::write_fst(df.durations,"durations_seconds.fst", compress = 100)
df.durations<-durations/(60*60) # duration for seconds to hours
df.durations<-round(df.durations,3)
df.durations<-as.data.frame(df.durations)
df.durations$cod_munic<-coords$codigo_ibge
fst::write_fst(df.durations,"durations_hours.fst", compress = 100)