r语言 - 如何将函数调用的结果平展为dplyr::mutate的一部分?



我有以下简单的用例,其中我定义了两个包含名称和位置的示例:

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))

最新更新