Ejemplo de leaflet
Cargo paquetes y data.
library(dplyr)
library(sf)
library(lubridate)
library(here)
'%!in%' <- function(x,y)!('%in%'(x,y))
library(leaflet)
library(RColorBrewer)
load(here::here("data", "df_gps_152.RData"))
Tomo las coordenadas de una de las cabeceras.
cabecera_lat_long <- c(long = -58.51257, lat = -34.51122)
cabecera <- data.frame(long = cabecera_lat_long["long"],
lat = cabecera_lat_long["lat"]) %>%
st_as_sf(coords = c("long", "lat"),
crs = 4326) %>%
st_transform(crs = 5347)
Le lavo la cara a los datos y armo las columnas necesarias.
df_gps_152_staged <- df_gps_152 %>%
as.data.frame() %>%
filter(interno %!in% c("3", "99", "117", "72", "5", "26", "122")) %>%
filter(!(latitude == 0 & longitude == 0)) %>%
distinct(interno, date_time, .keep_all = TRUE)
df_gps_152_5347 <- df_gps_152_staged %>%
st_as_sf(coords = c("longitude", "latitude"),
crs = 4326,
remove = FALSE) %>%
st_transform(crs = 5347)
df_gps_152_5347 <- cbind(df_gps_152_5347,
df_gps_152_5347 %>% st_coordinates())
df_gps_152_5347 <- df_gps_152_5347 %>%
mutate(dist_cabecera = st_distance(geometry, cabecera) %>%
round() %>%
as.numeric())
# armo columnas extras
df_gps_152_5347 <- df_gps_152_5347 %>%
group_by(interno) %>%
arrange(interno, date_time) %>%
mutate(se_aleja_de_cabecera = dist_cabecera > lag(dist_cabecera),
en_cabecera = dist_cabecera <= 400,
delta_x_m = dist_cabecera - (dist_cabecera %>% lag()),
delta_t_s = difftime(date_time,
date_time %>% lag(),
units = "secs") %>% as.numeric()) %>%
mutate(v_kmph = (delta_x_m/delta_t_s*3.6) %>% abs() %>% round(2)) %>%
mutate(detenido = v_kmph <= 2)
A mapear ! Yupi.
Primero: obtengo subset de datos a mapear.
data <- df_gps_152_5347 %>%
filter(interno == "95") %>%
arrange(interno, date_time) %>%
mutate(rn = row_number()) %>%
mutate(popup_text = paste0("v: ", v_kmph, " km/h <br/> delta_t_s: ", delta_t_s, " s <br/> delta_x_m: ", delta_x_m, " m <br/> date_time: ", date_time, "."))
Lo segundo: ¡paletas!
pal <- colorFactor(
palette = topo.colors(2),
domain = data$se_aleja_de_cabecera)
pal2 <- colorFactor(
palette = rainbow(2),
domain = data$en_cabecera)
pal3 <- colorNumeric(
palette = "viridis",
domain = data$v_kmph)
pal4 <- colorFactor(
palette = RColorBrewer::brewer.pal(3, "Set1"),
domain = data$detenido)
Y finalmente: el mapa.
leaflet(data = data %>%
dplyr::filter(rn < 60),
width = "100%") %>%
addTiles() %>%
addMarkers(lng = cabecera_lat_long["long"],
lat = cabecera_lat_long["lat"]) %>%
addCircleMarkers(lng = ~longitude,
lat = ~latitude,
radius = 5,
color = ~pal(se_aleja_de_cabecera),
fillOpacity = 0.7,
label = ~(rn %>% as.character()),
labelOptions = labelOptions(noHide = T, opacity = 0.8),
group = "Alejamiento cabecera") %>%
addLegend("bottomright", pal = pal, values = ~se_aleja_de_cabecera, title = "Alejamiento cabecera", opacity = 1) %>%
addCircleMarkers(lng = ~longitude,
lat = ~latitude,
radius = 5,
color = ~pal2(en_cabecera),
fillOpacity = 0.7,
label = ~(rn %>% as.character()),
labelOptions = labelOptions(noHide = T, opacity = 0.8),
group = "En cabecera") %>%
addLegend("bottomright", pal = pal2, values = ~en_cabecera, title = "En cabecera", opacity = 1) %>%
addCircleMarkers(lng = ~longitude,
lat = ~latitude,
radius = ~v_kmph,
color = ~pal3(v_kmph),
fillOpacity = 0.7,
label = ~(rn %>% as.character()),
labelOptions = labelOptions(noHide = T, opacity = 0.8),
popup = ~popup_text,
group = "Velocidad") %>%
addLegend("bottomright", pal = pal3, values = ~v_kmph, title = "Velocidad", opacity = 1) %>%
addCircleMarkers(lng = ~longitude,
lat = ~latitude,
radius = 5,
color = ~pal4(detenido),
fillOpacity = 1,
label = ~(rn %>% as.character()),
labelOptions = labelOptions(noHide = T, opacity = 0.8),
group = "Detenido") %>%
addLegend("bottomright", pal = pal4, values = ~detenido, title = "Detenido", opacity = 1) %>%
addLayersControl(overlayGroups = c("Alejamiento cabecera", "En cabecera", "Velocidad", "Detenido"),
options = layersControlOptions(collapsed = FALSE),
position = "bottomleft") %>%
hideGroup(c("En cabecera", "Velocidad", "Detenido")) %>%
addMeasure(primaryLengthUnit = "meters", position = "bottomleft") %>%
leaflet.extras::addFullscreenControl()
Nota del autor: Se apreciará el no-juicio estético de un mapa que ha sido creado para analizar y testear herramientas.
Nota del autor 2: “En mi PC funcionaba”. En realidad se veía más grande. Leaflet arreglame el full-screen.
Anyways: Carpe díem.
LS0tDQp0aXRsZTogIkxlYWZsZXQgc2hvd2Nhc2UiDQphdXRob3I6ICJBbmR5IEFiIg0KZGF0ZTogIkVuZXJvIDIwMjAiDQpvdXRwdXQ6DQogICAgaHRtbF9kb2N1bWVudDoNCiAgICAgICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgICAgICBkZl9wcmludDogcGFnZWQNCiAgICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCiMjIEVqZW1wbG8gZGUgbGVhZmxldA0KDQpDYXJnbyBwYXF1ZXRlcyB5IGRhdGEuDQoNCmBgYHtyIHBhY2thZ2UgbG9hZCwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShzZikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShoZXJlKQ0KJyUhaW4lJyA8LSBmdW5jdGlvbih4LHkpISgnJWluJScoeCx5KSkNCmxpYnJhcnkobGVhZmxldCkNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KDQpsb2FkKGhlcmU6OmhlcmUoImRhdGEiLCAiZGZfZ3BzXzE1Mi5SRGF0YSIpKQ0KDQpgYGANCg0KVG9tbyBsYXMgY29vcmRlbmFkYXMgZGUgdW5hIGRlIGxhcyBjYWJlY2VyYXMuDQogICAgDQpgYGB7ciBjYWJlY2VyYX0NCg0KY2FiZWNlcmFfbGF0X2xvbmcgPC0gYyhsb25nID0gLTU4LjUxMjU3LCBsYXQgPSAtMzQuNTExMjIpDQoNCmNhYmVjZXJhIDwtIGRhdGEuZnJhbWUobG9uZyA9IGNhYmVjZXJhX2xhdF9sb25nWyJsb25nIl0sDQogICAgICAgICAgICAgICAgICAgICAgIGxhdCA9IGNhYmVjZXJhX2xhdF9sb25nWyJsYXQiXSkgJT4lIA0KICAgIHN0X2FzX3NmKGNvb3JkcyA9IGMoImxvbmciLCAibGF0IiksDQogICAgICAgICAgICAgY3JzID0gNDMyNikgJT4lIA0KICAgIHN0X3RyYW5zZm9ybShjcnMgPSA1MzQ3KQ0KDQpgYGANCg0KTGUgbGF2byBsYSBjYXJhIGEgbG9zIGRhdG9zIHkgYXJtbyBsYXMgY29sdW1uYXMgbmVjZXNhcmlhcy4NCg0KYGBge3IgY2xlYW5pbmcgeSBwcmVwcm9jZXNzaW5nfQ0KDQpkZl9ncHNfMTUyX3N0YWdlZCA8LSBkZl9ncHNfMTUyICU+JQ0KICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICAgZmlsdGVyKGludGVybm8gJSFpbiUgYygiMyIsICI5OSIsICIxMTciLCAiNzIiLCAiNSIsICIyNiIsICIxMjIiKSkgJT4lDQogICAgZmlsdGVyKCEobGF0aXR1ZGUgPT0gMCAmIGxvbmdpdHVkZSA9PSAwKSkgJT4lIA0KICAgIGRpc3RpbmN0KGludGVybm8sIGRhdGVfdGltZSwgLmtlZXBfYWxsID0gVFJVRSkNCg0KZGZfZ3BzXzE1Ml81MzQ3IDwtIGRmX2dwc18xNTJfc3RhZ2VkICU+JQ0KICAgIHN0X2FzX3NmKGNvb3JkcyA9IGMoImxvbmdpdHVkZSIsICJsYXRpdHVkZSIpLA0KICAgICAgICAgICAgIGNycyA9IDQzMjYsDQogICAgICAgICAgICAgcmVtb3ZlID0gRkFMU0UpICU+JQ0KICAgIHN0X3RyYW5zZm9ybShjcnMgPSA1MzQ3KQ0KDQpkZl9ncHNfMTUyXzUzNDcgPC0gY2JpbmQoZGZfZ3BzXzE1Ml81MzQ3LA0KICAgICAgICAgICAgICAgICAgICAgICAgIGRmX2dwc18xNTJfNTM0NyAlPiUgc3RfY29vcmRpbmF0ZXMoKSkNCg0KZGZfZ3BzXzE1Ml81MzQ3IDwtIGRmX2dwc18xNTJfNTM0NyAlPiUgDQogICAgbXV0YXRlKGRpc3RfY2FiZWNlcmEgPSBzdF9kaXN0YW5jZShnZW9tZXRyeSwgY2FiZWNlcmEpICU+JSANCiAgICAgICAgICAgICAgIHJvdW5kKCkgJT4lIA0KICAgICAgICAgICAgICAgYXMubnVtZXJpYygpKQ0KDQojIGFybW8gY29sdW1uYXMgZXh0cmFzDQpkZl9ncHNfMTUyXzUzNDcgPC0gZGZfZ3BzXzE1Ml81MzQ3ICU+JSANCiAgICBncm91cF9ieShpbnRlcm5vKSAlPiUgDQogICAgYXJyYW5nZShpbnRlcm5vLCBkYXRlX3RpbWUpICU+JSANCiAgICBtdXRhdGUoc2VfYWxlamFfZGVfY2FiZWNlcmEgPSBkaXN0X2NhYmVjZXJhID4gbGFnKGRpc3RfY2FiZWNlcmEpLA0KICAgICAgICAgICBlbl9jYWJlY2VyYSA9IGRpc3RfY2FiZWNlcmEgPD0gNDAwLA0KICAgICAgICAgICBkZWx0YV94X20gPSBkaXN0X2NhYmVjZXJhIC0gKGRpc3RfY2FiZWNlcmEgJT4lIGxhZygpKSwNCiAgICAgICAgICAgZGVsdGFfdF9zID0gZGlmZnRpbWUoZGF0ZV90aW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRlX3RpbWUgJT4lIGxhZygpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0cyA9ICJzZWNzIikgJT4lIGFzLm51bWVyaWMoKSkgJT4lIA0KICAgIG11dGF0ZSh2X2ttcGggPSAoZGVsdGFfeF9tL2RlbHRhX3RfcyozLjYpICU+JSBhYnMoKSAlPiUgcm91bmQoMikpICU+JSANCiAgICBtdXRhdGUoZGV0ZW5pZG8gPSB2X2ttcGggPD0gMikNCg0KYGBgDQoNCkEgbWFwZWFyICENCll1cGkuDQoNClByaW1lcm86IG9idGVuZ28gc3Vic2V0IGRlIGRhdG9zIGEgbWFwZWFyLg0KDQpgYGB7ciBkYXRhfQ0KDQpkYXRhIDwtIGRmX2dwc18xNTJfNTM0NyAlPiUNCiAgICBmaWx0ZXIoaW50ZXJubyA9PSAiOTUiKSAlPiUNCiAgICBhcnJhbmdlKGludGVybm8sIGRhdGVfdGltZSkgJT4lIA0KICAgIG11dGF0ZShybiA9IHJvd19udW1iZXIoKSkgJT4lIA0KICAgIG11dGF0ZShwb3B1cF90ZXh0ID0gcGFzdGUwKCJ2OiAiLCB2X2ttcGgsICIga20vaCA8YnIvPiBkZWx0YV90X3M6ICIsIGRlbHRhX3RfcywgIiBzIDxici8+IGRlbHRhX3hfbTogIiwgZGVsdGFfeF9tLCAiIG0gPGJyLz4gZGF0ZV90aW1lOiAiLCBkYXRlX3RpbWUsICIuIikpDQoNCg0KYGBgDQoNCkxvIHNlZ3VuZG86IMKhcGFsZXRhcyENCg0KYGBge3IgcGFsZXRhc30NCg0KcGFsIDwtIGNvbG9yRmFjdG9yKA0KICAgIHBhbGV0dGUgPSB0b3BvLmNvbG9ycygyKSwNCiAgICBkb21haW4gPSBkYXRhJHNlX2FsZWphX2RlX2NhYmVjZXJhKQ0KcGFsMiA8LSBjb2xvckZhY3RvcigNCiAgICBwYWxldHRlID0gcmFpbmJvdygyKSwNCiAgICBkb21haW4gPSBkYXRhJGVuX2NhYmVjZXJhKQ0KcGFsMyA8LSBjb2xvck51bWVyaWMoDQogICAgcGFsZXR0ZSA9ICJ2aXJpZGlzIiwNCiAgICBkb21haW4gPSBkYXRhJHZfa21waCkNCnBhbDQgPC0gY29sb3JGYWN0b3IoDQogICAgcGFsZXR0ZSA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCgzLCAiU2V0MSIpLA0KICAgIGRvbWFpbiA9IGRhdGEkZGV0ZW5pZG8pDQoNCmBgYA0KDQpZIGZpbmFsbWVudGU6IGVsIG1hcGEuDQoNCmBgYHtyIG1hcCwgaGVpZ2h0ID0gMTAwLCB3aWR0aCA9IDEwMH0NCg0KbGVhZmxldChkYXRhID0gZGF0YSAlPiUNCiAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIocm4gPCA2MCksDQogICAgICAgIHdpZHRoID0gIjEwMCUiKSAlPiUgIA0KICAgIGFkZFRpbGVzKCkgJT4lIA0KICAgIGFkZE1hcmtlcnMobG5nID0gY2FiZWNlcmFfbGF0X2xvbmdbImxvbmciXSwNCiAgICAgICAgICAgICAgIGxhdCA9IGNhYmVjZXJhX2xhdF9sb25nWyJsYXQiXSkgJT4lDQogICAgYWRkQ2lyY2xlTWFya2VycyhsbmcgPSB+bG9uZ2l0dWRlLA0KICAgICAgICAgICAgICAgICAgICAgbGF0ID0gfmxhdGl0dWRlLA0KICAgICAgICAgICAgICAgICAgICAgcmFkaXVzID0gNSwNCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gfnBhbChzZV9hbGVqYV9kZV9jYWJlY2VyYSksDQogICAgICAgICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IDAuNywNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gfihybiAlPiUgYXMuY2hhcmFjdGVyKCkpLA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWxPcHRpb25zID0gbGFiZWxPcHRpb25zKG5vSGlkZSA9IFQsIG9wYWNpdHkgPSAwLjgpLA0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSAiQWxlamFtaWVudG8gY2FiZWNlcmEiKSAlPiUgDQogICAgYWRkTGVnZW5kKCJib3R0b21yaWdodCIsIHBhbCA9IHBhbCwgdmFsdWVzID0gfnNlX2FsZWphX2RlX2NhYmVjZXJhLCB0aXRsZSA9ICJBbGVqYW1pZW50byBjYWJlY2VyYSIsIG9wYWNpdHkgPSAxKSAlPiUgDQogICAgYWRkQ2lyY2xlTWFya2VycyhsbmcgPSB+bG9uZ2l0dWRlLA0KICAgICAgICAgICAgICAgICAgICAgbGF0ID0gfmxhdGl0dWRlLA0KICAgICAgICAgICAgICAgICAgICAgcmFkaXVzID0gNSwNCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gfnBhbDIoZW5fY2FiZWNlcmEpLA0KICAgICAgICAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAwLjcsDQogICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IH4ocm4gJT4lIGFzLmNoYXJhY3RlcigpKSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucyhub0hpZGUgPSBULCBvcGFjaXR5ID0gMC44KSwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gIkVuIGNhYmVjZXJhIikgJT4lDQogICAgYWRkTGVnZW5kKCJib3R0b21yaWdodCIsIHBhbCA9IHBhbDIsIHZhbHVlcyA9IH5lbl9jYWJlY2VyYSwgdGl0bGUgPSAiRW4gY2FiZWNlcmEiLCBvcGFjaXR5ID0gMSkgJT4lIA0KICAgIGFkZENpcmNsZU1hcmtlcnMobG5nID0gfmxvbmdpdHVkZSwNCiAgICAgICAgICAgICAgICAgICAgIGxhdCA9IH5sYXRpdHVkZSwNCiAgICAgICAgICAgICAgICAgICAgIHJhZGl1cyA9IH52X2ttcGgsDQogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IH5wYWwzKHZfa21waCksDQogICAgICAgICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IDAuNywNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gfihybiAlPiUgYXMuY2hhcmFjdGVyKCkpLA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWxPcHRpb25zID0gbGFiZWxPcHRpb25zKG5vSGlkZSA9IFQsIG9wYWNpdHkgPSAwLjgpLA0KICAgICAgICAgICAgICAgICAgICAgcG9wdXAgPSB+cG9wdXBfdGV4dCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gIlZlbG9jaWRhZCIpICU+JSANCiAgICBhZGRMZWdlbmQoImJvdHRvbXJpZ2h0IiwgcGFsID0gcGFsMywgdmFsdWVzID0gfnZfa21waCwgdGl0bGUgPSAiVmVsb2NpZGFkIiwgb3BhY2l0eSA9IDEpICU+JSANCiAgICBhZGRDaXJjbGVNYXJrZXJzKGxuZyA9IH5sb25naXR1ZGUsDQogICAgICAgICAgICAgICAgICAgICBsYXQgPSB+bGF0aXR1ZGUsDQogICAgICAgICAgICAgICAgICAgICByYWRpdXMgPSA1LA0KICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSB+cGFsNChkZXRlbmlkbyksDQogICAgICAgICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IDEsDQogICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IH4ocm4gJT4lIGFzLmNoYXJhY3RlcigpKSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucyhub0hpZGUgPSBULCBvcGFjaXR5ID0gMC44KSwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gIkRldGVuaWRvIikgJT4lDQogICAgYWRkTGVnZW5kKCJib3R0b21yaWdodCIsIHBhbCA9IHBhbDQsIHZhbHVlcyA9IH5kZXRlbmlkbywgdGl0bGUgPSAiRGV0ZW5pZG8iLCBvcGFjaXR5ID0gMSkgJT4lDQogICAgYWRkTGF5ZXJzQ29udHJvbChvdmVybGF5R3JvdXBzID0gYygiQWxlamFtaWVudG8gY2FiZWNlcmEiLCAiRW4gY2FiZWNlcmEiLCAiVmVsb2NpZGFkIiwgIkRldGVuaWRvIiksDQogICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gRkFMU0UpLA0KICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSAiYm90dG9tbGVmdCIpICU+JQ0KICAgIGhpZGVHcm91cChjKCJFbiBjYWJlY2VyYSIsICJWZWxvY2lkYWQiLCAiRGV0ZW5pZG8iKSkgJT4lDQogICAgYWRkTWVhc3VyZShwcmltYXJ5TGVuZ3RoVW5pdCA9ICJtZXRlcnMiLCBwb3NpdGlvbiA9ICJib3R0b21sZWZ0IikgJT4lDQogICAgbGVhZmxldC5leHRyYXM6OmFkZEZ1bGxzY3JlZW5Db250cm9sKCkNCg0KYGBgDQoNCipOb3RhIGRlbCBhdXRvcjogU2UgYXByZWNpYXLDoSBlbCBuby1qdWljaW8gZXN0w6l0aWNvIGRlIHVuIG1hcGEgcXVlIGhhIHNpZG8gY3JlYWRvIHBhcmEgYW5hbGl6YXIgeSB0ZXN0ZWFyIGhlcnJhbWllbnRhcy4qDQoNCipOb3RhIGRlbCBhdXRvciAyOiAiRW4gbWkgUEMgZnVuY2lvbmFiYSIuIEVuIHJlYWxpZGFkIHNlIHZlw61hIG3DoXMgZ3JhbmRlLiBMZWFmbGV0IGFycmVnbGFtZSBlbCBmdWxsLXNjcmVlbi4qDQoNCkFueXdheXM6IENhcnBlIGTDrWVtLg0KDQo=