sta*_*oob 5 r data-visualization geospatial leaflet
我正在使用 R 编程语言。
使用“leaflet”库,我为这 5 个城市制作了以下地图:
library(dplyr)
library(leaflet)
map_data <- data.frame("Lat" = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), "Long" = c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ), type = c(1,2,3,4,5))
map_data$type = as.factor(map_data$type)
leaflet(map_data) %>%
addTiles() %>% addCircleMarkers(stroke = FALSE, label = ~type,fillOpacity = 0.8, labelOptions = labelOptions(direction = "center",style = list('color' = "white"),noHide = TRUE, offset=c(0,0), fill = TRUE, opacity = 1, weight = 10, textOnly = TRUE))
Run Code Online (Sandbox Code Playgroud)
在我创建的上面的地图上,我现在想根据它们的“数字”“连接”地图上(在路线中)的所有这些“点”(即城市)(例如,将 1 与 2、2 与 3 连接) , 3 与 4, 4 与 5, 5 与 1),并输出路线的“总距离”。我发现之前的一篇文章展示了如何执行此操作:How to show path and distance on map with leaflet, Sparkly apps?
我尝试调整这篇文章中的代码来适应我的问题:
library(osrm)
route = osrmRoute(c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ), c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), overview = 'full')
route_summary = osrmRoute(c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ), c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), overview = FALSE)
leaflet() %>% addTiles() %>%
addCircleMarkers(c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ), c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), stroke = FALSE, label = ~type,fillOpacity = 0.8,
labelOptions = labelOptions(direction = "center",style = list('color' = "white"),noHide = TRUE, offset=c(0,0), fill = TRUE, opacity = 1, weight = 10, textOnly = TRUE)) %>%
addPolylines(route$lon,route$lat,
label = paste(round(route_summary[1]/60), 'hr - ', round(route_summary[2]), 'km'),
labelOptions = labelOptions(noHide = TRUE))
Run Code Online (Sandbox Code Playgroud)
但这会返回以下错误:
Error in UseMethod("metaData") :
no applicable method for 'metaData' applied to an object of class "NULL"
Run Code Online (Sandbox Code Playgroud)
有人可以告诉我如何解决这个问题吗?
我想使用“传单”而不是“rshiny”来做到这一点。最后,我希望最终的地图看起来像这样(这应该代表旅行商问题的“单一路径”):
[![在此处输入图像描述][2]][2]
注意:我开始认为问题可能是“osrmRoute()”函数可能无法工作超过 2 个点?
一种方法是进行 API 调用:
https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md
我将概述如何做到这一点:
数据
df <- data.frame(
lon = c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957),
lat = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629)
)
Run Code Online (Sandbox Code Playgroud)
网址调用
root <- "http://router.project-osrm.org/route/v1/driving/"
options <- c(
continue_straight = "true",
overview = "full",
annotations = "true",
steps = "true"
)
coords <- df %>%
slice(c(seq_len(n()), 1)) %>%
pmap_chr(str_c, sep = ",") %>% str_c(collapse = ";")
options <- options %>%
imap_chr(~str_c(.y, "=", .x)) %>%
str_c(collapse = "&") %>%
str_c("?", .)
res <- rjson::fromJSON(file = str_c(root, coords, options))
Run Code Online (Sandbox Code Playgroud)
请注意,我已将第一个点添加为第六行以制作圆形路线。
地图
res$routes[[1]]$geometry %>%
googlePolylines::decode() %>%
.[[1]] %>%
leaflet() %>%
addTiles() %>%
addPolylines(lng = ~lon, lat = ~lat) %>%
addCircleMarkers(
data = df,
stroke = FALSE,
label = seq_len(nrow(df)),
fillOpacity = 0.8,
labelOptions = labelOptions(
direction = "center",
style = list('color' = "white"),
noHide = TRUE,
offset=c(0,0),
fill = TRUE,
opacity = 1,
weight = 10,
textOnly = TRUE
)
)
Run Code Online (Sandbox Code Playgroud)
距离
res$routes[[1]]$distance
Run Code Online (Sandbox Code Playgroud)
这是以米为单位(文档)
编辑
可能有更好的方法来标记折线,但我现在没有时间:
library(sf)
segment_df <- df %>% rbind(df[1,])
d <- segment_df %>%
st_as_sf(coords = c("lon", "lat"), crs = 4326) %>%
{st_distance(.[-6,], .[-1,], by_element = TRUE)} %>%
as.vector() %>%
round()
m <- leaflet() %>% addTiles()
for(i in seq_len(nrow(segment_df) - 1))
m <- m %>% addPolylines(
data = segment_df[i:(i+1),],
lng = ~lon, lat = ~lat, color = "red", label = paste(d[[i]], "m"),
labelOptions(noHide = TRUE, direction = 'top')
)
m <- m %>% addCircleMarkers(
data = df,
stroke = FALSE,
label = seq_len(nrow(df)),
fillOpacity = 0.8,
labelOptions = labelOptions(
direction = "center",
style = list('color' = "white"),
noHide = TRUE,
offset=c(0,0),
fill = TRUE,
opacity = 1,
weight = 10,
textOnly = TRUE
)
)
Run Code Online (Sandbox Code Playgroud)
如果您只想显示总距离,那么这更容易并且不需要循环,只需将循环替换为:
segment_df %>%
leaflet() %>%
addTiles() %>%
addPolylines(
lng = ~lon, lat = ~lat, color = "red",
label = paste(sum(d), "m"),
labelOptions = labelOptions(noHide = TRUE, direction = 'top')
)
Run Code Online (Sandbox Code Playgroud)
我希望您明白(并从地图上看到)这是无法驾驶的。