查看原文
其他

在 R 语言里面调用高德地图接口:地理编码与路径规划

RStata RStata 2022-05-17

你知道从广州南站去珠江新城怎么走么?今天就让我们一起使用 R 语言调用高德地图的地理编码(地址转经纬度)接口和路径规划接口来回答这个问题。

准备工作

注册高德地图,创建应用添加 Key(注意申请 Key 的时候服务平台应该选择“Web 服务”)。

  • 高德地图创建应用页面链接:https://lbs.amap.com/dev/key/app
  • 高德地图开发者文档 - 地理/逆地理编码:https://lbs.amap.com/api/webservice/guide/api/georegeo
  • 高德地图开发者文档 - 路径规划:https://lbs.amap.com/api/webservice/guide/api/direction

从广州南站去往珠江新城

首先加载下面的操作中需要的 R 包:

library(jsonlite)
library(magrittr)
library(sf)
library(tidyverse)

设定高德地图密钥:

key <- Sys.getenv("amap.key")

设定我们的起止点:

start = "广州南站"
end = "广州珠江新城"

进行路径规划前我们先要把地址转换成经纬度:

# 查询起始点的经纬度
fromJSON(paste0('https://restapi.amap.com/v3/geocode/geo?address=', start, '&key=', key)) -> start
start$geocodes$location -> start
start
#> [1] "113.267080,22.988342"

fromJSON(paste0('https://restapi.amap.com/v3/geocode/geo?address=', end, '&key=', key)) -> end
end$geocodes$location -> end
end
#> [1] "113.327343,23.119274"

下面我们进行步行规划:

route <- fromJSON(paste0("https://restapi.amap.com/v3/direction/walking?origin=", start, "&destination=", end, "&key=", key))
# 距离
route$route$paths$distance
#> [1] "24003"

# 时间
route$route$paths$duration
#> [1] "19202"

route$route$paths$steps %>% 
  as.data.frame() %>% 
  as_tibble() -> steps
steps

#> # A tibble: 73 x 9
#>    instruction orientation road  distance duration polyline action
#>    <chr>       <list>      <lis> <chr>    <chr>    <chr>    <list>
#>  1 向北步行664米向右… <chr [1]>   <chr… 664      531      113.266… <chr …
#>  2 沿石浦大道北步行42… <chr [0]>   <chr… 42       34       113.267… <chr …
#>  3 步行24米向左前方行… <chr [0]>   <chr… 24       19       113.268… <chr …
#>  4 沿石浦大道北向西北步… <chr [1]>   <chr… 20       16       113.268… <chr …
#>  5 沿石洲西路向东北步行… <chr [1]>   <chr… 18       14       113.267… <chr …
#>  6 步行26米右转… <chr [0]>   <chr… 26       21       113.268… <chr …
#>  7 沿钟南大道步行25米… <chr [0]>   <chr… 25       20       113.268… <chr …
#>  8 沿石洲西路向东北步行… <chr [1]>   <chr… 156      125      113.268… <chr …
#>  9 沿石陈路向北步行27… <chr [1]>   <chr… 270      216      113.269… <chr …
#> 10 沿石韦路向北步行51… <chr [1]>   <chr… 515      412      113.270… <chr …
#> # … with 63 more rows, and 2 more variables: assistant_action <list>,
#> #   walk_type <chr>

steps %>% 
  select(polyline) %>% 
  tidytext::unnest_tokens(polyline, polyline, 
                          token = stringr::str_split, pattern = ";") %>% 
  distinct() %>% 
  separate(col = "polyline", into = c("lon""lat"), sep = ",") %>% 
  type_convert() -> pathdf
pathdf

#> # A tibble: 561 x 2
#>      lon   lat
#>    <dbl> <dbl>
#>  1  113.  23.0
#>  2  113.  23.0
#>  3  113.  23.0
#>  4  113.  23.0
#>  5  113.  23.0
#>  6  113.  23.0
#>  7  113.  23.0
#>  8  113.  23.0
#>  9  113.  23.0
#> 10  113.  23.0
#> # … with 551 more rows

pathdf %>% 
  as.matrix() %>% 
  st_linestring() -> pathsf

最后得到的 pathsf 是个 LINESTRING,我们可以把它绘制在地图上:

library(leaflet)
library(leafem)
library(leafletCN)
leaflet(width = "100%", height = "400px") %>% 
  amap() %>% 
  addFeatures(data = pathsf, color = "red", weight = 10)

再用手机上的高德地图对比下:

是不是几乎一样哈哈!

这个地图正是使用高德地图作为地图。根据我们之前介绍的方法,我们还可以给这个地图添加标题:

# 为 leaflet 地图添加标题(这个标题在 RMarkdown 文档里似乎无法显示)
library(htmltools)
tag.map.title <- tags$style(HTML("
  .leaflet-control.map-title { 
    transform: translate(-50%,20%);
    position: fixed ;
    left: 50%;
    text-align: center;
    padding-left: 10px; 
    padding-right: 10px; 
    background: rgba(255,255,255,0.75);
    font-weight: bold;
    font-size: 22px;
  }
"
))
title <- tags$div(
  tag.map.title, HTML("从广州南站到珠江新城怎么走?")
)
leaflet(width = "100%", height = "400px") %>% 
  amap() %>% 
  addFeatures(data = pathsf, color = "red", weight = 10) %>% 
  addControl(title, position = "topleft", className = "map-title")

函数封装

我们可以把上面的操作封装成一个函数使用:

pathsf <- function(start_point = "广州南站",
                   end_point = "广州珠江新城",
                   by = "walking"){
  fromJSON(paste0('https://restapi.amap.com/v3/geocode/geo?address=', start_point, '&key=', key)) -> start
  start$geocodes$location -> start
  fromJSON(paste0('https://restapi.amap.com/v3/geocode/geo?address=', end_point, '&key=', key)) -> end
  end$geocodes$location -> end
  route <- fromJSON(paste0("https://restapi.amap.com/v3/direction/", by, "?origin=", start, "&destination=", end, "&key=", key))
  dist <- route$route$paths$distance
  duration <- route$route$paths$duration
  route$route$paths$steps %>% 
    as.data.frame() %>% 
    as_tibble() -> steps
  steps %>% 
    select(polyline) %>% 
    tidytext::unnest_tokens(polyline, polyline, 
                            token = stringr::str_split, pattern = ";") %>% 
    distinct() %>% 
    separate(col = "polyline", into = c("lon""lat"), sep = ",") %>% 
    type_convert() %>% 
    as.matrix() %>% 
    st_linestring() -> path
  return(list(path = path, dist = dist, duration = duration))
}

使用:

walking <- pathsf()
driving <- pathsf(by = 'driving')

# 地图展示
leaflet(width = "100%", height = "400px") %>% 
  amap() %>% 
  addFeatures(data = walking$path, color = "red", weight = 10) %>% 
  addFeatures(data = driving$path, color = "green", weight = 10) %>% 
  addMouseCoordinates()

在数据框中使用

掌握如何在数据框中使用非常重要,毕竟我们接触的数据大多是表式的。我们构造一个示例数据框:

address <- tibble(
  start = c("广州南站""广州珠江新城""广州海心沙亚运公园""广州塔地铁站"),
  end = c("广州珠江新城""广州海心沙亚运公园""广州塔地铁站""广州南站")
)

library(purrr)
address %>% 
  mutate(pathsf = map2(start, end, pathsf)) -> address

# 地图展示
leaflet(width = "100%", height = "400px") %>% 
  amap() %>% 
  addFeatures(data = address$pathsf[[1]]$path, color = "red", weight = 10) %>% 
  addFeatures(data = address$pathsf[[2]]$path, color = "green", weight = 10) %>% 
  addFeatures(data = address$pathsf[[3]]$path, color = "blue", weight = 10) %>% 
  addFeatures(data = address$pathsf[[4]]$path, color = "pink", weight = 10)

好啦,今天的教程就到这里了。

如果有兴趣深入学习,可以从短书平台(点击阅读原文即可跳转:https://rstata.duanshu.com/#/)上获取这个课程的视频讲解:


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存