Open Eflores89 opened 8 years ago
Justamente estaba buscando algo así con el API de Google, pero tiene limite de 2500 consultas diarias y no me es suficiente. Lo veo en estos días
Ya empecé a jugar con el código, y tengo dos observaciones/dudas iniciales:
1)los siguientes parámetros de entrada no están nada claro:
2) Al cambiar el layout de lo que hay en la funcion paste0 pude hacer funcionar el codigo (me estaba arrojando error con los \n)
from <- c(82233,82234,633281) #copie los valores del ejemplo del API
to <- c(218261,113968)
inegi_route <- function(from, to, route_type = 2, vehicle = 1, axis = 0, type = 1, token){
if(type == 1){
# linea a linea
if(length(from)==2){}else{stop("Length of from parameter must be 2. A vector with source id and target id, in that order")}
if(length(to)==2){}else{stop("Length of to parameter must be 2. A vector with source id and target id, in that order")}
q <- paste0("http://gaia.inegi.org.mx/sakbe/wservice?make=CR&id_i=1&source_i=",
from[1],
"&target_i=",
from[2],
"&id_f=", from[3],
"&source_f=", to[1],
"&target_f=", to[2],
"&p=", route_type,
"&v=", vehicle,
"&e=", axis,
"&type=xml&key=", token)
m <- "line to line"
}else{
if(type == 2){
q <- paste0("http://gaia.inegi.org.mx/sakbe/wservice?make=CR",
"&dest_i=",from,
"&dest_f=", to,
"&p=", route_type,
"&v=", vehicle,
"&e=", axis,
"&type=xml&key=",token)
m <- "destiny to destiny"
}else{
if(type == 3){
}else{
if(type == 4){
}else{stop("Type of query unrecognized. Use 1 through 4.")}
}
}
}
d <- XML::xmlToList(q)
df <- data.frame("ROUTE_STRING" = paste0("Route, ", m,
" id: ", from[1],
" to id: ", to[1]),
"SQL_STRING" = ifelse(is.null(d$ruta$sql), NA, as.character(d$ruta$sql)),
"ROUTE_LENGTH" = ifelse(is.null(d$ruta$long_km), NA, as.numeric(d$ruta$long_km)),
"ROUTE_TIME" = ifelse(is.null(d$ruta$tiempo_min), NA, as.numeric(d$ruta$tiempo_min)),
"ROUTE_TOLL" = ifelse(is.null(d$ruta$peaje), NA,
ifelse(as.character(d$ruta$peaje)=="t", TRUE,FALSE)),
"ROUTE_COST" = ifelse(is.null(d$ruta$costo_caseta), NA, as.numeric(d$ruta$costo_caseta)),
"ROUTE_EXCEED" = ifelse(is.null(d$ruta$eje_excedente), NA, as.numeric(d$ruta$eje_excedente))
)
l <- list("METADATA" = df,
"GEO" = jsonlite::fromJSON(as.character(d$ruta$geojson)))
return(l)
}
Continuaré con esto...
Exactamente!! Traté de encontrar por todos lados, pero no se preocupan NADA por dejar claro que son los parámetros...
Segun http://antares.inegi.org.mx/analisis/red_hidro/SIATL/ cuando deseas trazar una ruta te sale el siguiente aviso:
Encontré un poco más de información en el siguiente documento:
http://www.inegi.org.mx/saladeprensa/aproposito/2015/caminero0.pdf
Ok... aquí va lo que llevo.
inegi_lines <- function(latitud, longitud, scale = 100000, keep_trying = TRUE, token){
options(scipen = 999)
if(keep_trying){
d <- NULL
while(is.null(d$linea)){
print(paste0("Using scale: ", scale))
if(scale<1){d$linea <- NA # if already extended all attempts
}else{
q <- paste0("http://gaia.inegi.org.mx/sakbe/wservice?make=IL",
"&x=", longitud,
"&y=", latitud,
"&escala=", scale,
"&type=xml&key=", token)
d <- XML::xmlToList(q)
scale <- scale/10
}
}
}else{
print(paste0("Using scale: ", scale))
q <- paste0("http://gaia.inegi.org.mx/sakbe/wservice?make=IL",
"&x=", longitud,
"&y=", latitud,
"&escala=", scale,
"&type=xml&key=", token)
d <- XML::xmlToList(q)
}
if(is.null(d$linea)){stop("Nothing returned. Try with different scale or keep_trying = true")}
if(suppressWarnings(is.na(d$linea))){stop("Nothing returned. Try with different scale or keep_trying = true")}
df <- as.data.frame(d$linea)
print(df)
return(df)
}
Unica modificación que hice a la función inegi_lines() es la del formato de los números para evitar que se utilicen notaciones científicas (esto me generó problemas al tratar de correr la formula en mi computadora)
En cuanto a inegi_route() aquí empieza lo interesante:
inegi_route <- function(from_io, to_io, route_type = 2, vehicle = 1, axis = 0, type = 1, token){
#use inegi_lines() to obtain id, source and target for the routes
from <- inegi_lines(latitud=from_io[1],longitud=from_io[2],scale=10000000,keep_trying = TRUE, token = token)
to <- inegi_lines(latitud=to_io[1],longitud=to_io[2],scale=10000000,keep_trying = TRUE, token = token)
if(type == 1){
# linea a linea
if(length(from)==5){}else{stop("Length of from parameter must be 2. A vector with source id and target id, in that order")}
if(length(to)==5){}else{stop("Length of to parameter must be 2. A vector with source id and target id, in that order")}
q <- paste0("http://gaia.inegi.org.mx/sakbe/wservice?make=CR&",
"id_i=",from[1,1], #need this [1,1] to specifiy the correct value from the variable
"&source_i=", from[1,2],
"&target_i=",from[1,2],
"&id_f=", to[1,2],
"&source_f=", to[1,2],
"&target_f=", to[1,2],
"&p=", route_type,
"&v=", vehicle,
"&e=", axis,
"&type=xml&key=", token)
m <- "line to line"
}else{
if(type == 2){
q <- paste0("http://gaia.inegi.org.mx/sakbe/wservice?make=CR",
"&dest_i=",from,
"&dest_f=", to,
"&p=", route_type,
"&v=", vehicle,
"&e=", axis,
"&type=xml&key=",token)
m <- "destiny to destiny"
}else{
# pending
if(type == 3){
# pending
}else{
if(type == 4){
# pending
}else{stop("Type of query unrecognized. Use 1 through 4.")}
}
}
}
d <- XML::xmlToList(q)
df <- data.frame("ROUTE_STRING" = paste0("Route, ", m,
" id: ", from[1,1],
" to id: ", to[1,1]),
"SQL_STRING" = ifelse(is.null(d$ruta$sql), NA, as.character(d$ruta$sql)),
"ROUTE_LENGTH" = ifelse(is.null(d$ruta$long_km), NA, as.numeric(d$ruta$long_km)),
"ROUTE_TIME" = ifelse(is.null(d$ruta$tiempo_min), NA, as.numeric(d$ruta$tiempo_min)),
"ROUTE_TOLL" = ifelse(is.null(d$ruta$peaje), NA,
ifelse(as.character(d$ruta$peaje)=="t", TRUE,FALSE)),
"ROUTE_COST" = ifelse(is.null(d$ruta$costo_caseta), NA, as.numeric(d$ruta$costo_caseta)),
"ROUTE_EXCEED" = ifelse(is.null(d$ruta$eje_excedente), NA, as.numeric(d$ruta$eje_excedente))
)
l <- list("METADATA" = df,
"GEO" = jsonlite::fromJSON(as.character(d$ruta$geojson)))
return(l)
}
A manera de prueba, busque la ruta desde el TEC de Monterrey hasta el Museo de Historia del Barrio Antiguo (Monterrey)
p1=c(25.671528, -100.306492) #museo de historia mexicano (monterrey)
p2=c(25.650443,-100.289725) #tec de monterrey
p3=c(29.081782, -110.961874) #centro hermosillo
test <- inegi_route(p1,p2,token=token)
mapa <- test$GEO$coordinates
library(leaflet)
map <- leaflet() %>%
addTiles() %>%
setView(p1[2], p1[1], zoom = 10) %>%
addCircleMarkers(lat = mapa[,2],
lng = mapa[,1],
radius = 3,
stroke = TRUE, fillOpacity = 0.5) %>%
addProviderTiles("CartoDB.Positron")
map
En caso de querer generar una función para "mapear" las coordenadas de distancias más largas, es necesario usar un do.call(). El siguiente ejemplo es la ruta desde el Tec de Monterrey hasta el centro de Hermosillo
p1=c(25.671528, -100.306492) #museo de historia mexicano (monterrey)
p2=c(25.650443,-100.289725) #tec de monterrey
p3=c(29.081782, -110.961874) #centro hermosillo
test <- inegi_route(p2,p3,token=token)
mapa <- do.call("rbind",test$GEO$coordinates)
library(leaflet)
map <- leaflet() %>%
addTiles() %>%
setView(p1[2], p1[1], zoom = 10) %>%
addCircleMarkers(lat = mapa[,2],
lng = mapa[,1],
radius = 3,
stroke = TRUE, fillOpacity = 0.5) %>%
addProviderTiles("CartoDB.Positron")
map
Espero que vayamos en la dirección correcta.
Comentarios?
O sea, como lo entiendo, la más directa es type == 1 que es coordenada a coordenada? Las demás podríamos simplemente omitir, ¿no? Por que en teoría con un "search" ya sale la coordenada...
Tengo pendiente trabajar en el "error handling" de estas dos funciones. Y también tengo interés en el detalle de ruta
duda, en qué quedó todo esto? ajaja
estaría bien acabarlo estos días que tengo vacaciones para ya publicarlo!
INEGI publicó un nuevo API que parece interesante para trazar rutas.
Hasta ahora solo eh podido incluir el de búsqueda de id's de destinos, (ver la función
inegi_destiny
).Le heche un vistazo también a la de líneas y tengo un avance:
Y la documentación del INEGI me trae vuelto loco con el trace de rutas. Pareciera que tiene muchas opciones y muchas no están explicadas correctamente. Llevo un avance en una funcionsita así...
@arturocm crees que podrías ayudarme a darle carpetazo al tema? Siento que ya tengo ceguera de taller y tal vez tengas ideas nuevas. Quiero sacar una versión 2.0 con este nuevo API, te pongo como coauthor, que ya haz hecho bastante también del DENUE.