我有以下简单的用例,其中我定义了两个包含名称和位置的示例:
if(!require(tidyverse)) install.packages("tidyverse", repos = "http://cran.us.r-project.org")
if(!require(ggmap)) devtools::install_github("dkahle/ggmap")
# you may also need to
#register_google(key="<register your own key>")
x <- tibble(name=c('a', 'b'), loc=c('china', 'switzerland'))
x
# A tibble: 2 x 2
name loc
<chr> <chr>
1 a china
2 b switzerland
现在我想用经度和纬度信息来丰富我的 tibble。我通过运行来做到这一点:
x %>%
mutate(lon=geocode(loc)$lon, lat=geocode(loc)$lat)
但这很昂贵,因为我需要为每个样本调用geocode
函数两次,而且 [s] 不是免费的。有没有办法将geocode
函数的返回展平化到tibble中?这是一次失败的尝试,也是我想要实现的目标的演示:
x %>%
mutate(xx=geocode(loc), lon=xx$lon, lat=xx$lat)
>Error: Column `xx` is of unsupported class data.frame
对于添加地理编码坐标的特定情况,ggmap
实际上有一个函数mutate_geocode
可以做到这一点:
library(dplyr)
library(ggmap)
mutate_geocode(x, location = loc)
#> # A tibble: 2 x 4
#> name loc lon lat
#> <chr> <chr> <dbl> <dbl>
#> 1 a china 104. 35.9
#> 2 b switzerland 8.23 46.8
对于更一般的用途,purrr::map_*
函数运行良好。您可以映射位置名称,应用geocode
,然后取消嵌套该列表:
mutate(x, coords = purrr::map(loc, geocode)) %>%
tidyr::unnest(coords)
# same output as above
您还可以使用purrr::map_dbl
提取所需的每列。如果您返回的数据框不仅包含 lon 和 lat 列,例如如果您在geocode
中设置了不同的output
值,这可能会很有帮助:
mutate(x, coords = purrr::map(loc, geocode),
lon = purrr::map_dbl(coords, "lon"),
lat = purrr::map_dbl(coords, "lat"))
# same output as above
或按列位置:
mutate(x, coords = purrr::map(loc, geocode),
lon = purrr::map_dbl(coords, 1),
lat = purrr::map_dbl(coords, 2))
# same output
可以将地理编码的输出放在list
中,然后提取组件
library(dplyr)
library(purrr)
library(ggmap)
library(tidyr)
x %>%
mutate(xx = map(loc, geocode),
out = map(xx, ~ tibble(lon = .x$lon, lat = .x$lat))) %>%
unnest_wider(c(out))