在一列嵌套数据框上实现map()

G_T*_*G_T 1 r dplyr magrittr purrr tidyverse

我正在自学R tidyverse purr()程序包,并且map()在一列嵌套数据帧上实现时遇到了麻烦。有人可以解释我所缺少的吗?

以基本的R ChickWeight数据集为例,如果我像这样首先过滤饮食#1,就可以轻松获取饮食#1下每个时间点的观察次数:

library(tidyverse) 
ChickWeight %>%
  filter(Diet == 1) %>% 
  group_by(Time) %>% 
  summarise(counts = n_distinct(Chick))
Run Code Online (Sandbox Code Playgroud)

很好,但我想一次为每种饮食做一次,我认为嵌套数据并对其进行迭代map()将是一个好方法。这是我所做的:

example <- ChickWeight %>% 
  nest(-Diet) 
Run Code Online (Sandbox Code Playgroud)

然后,实现此地图功能即可达到我的目标:

map(example$data, ~ .x %>% group_by(Time) %>% summarise(counts = n_distinct(Chick))) 
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试使用管道将同一命令放入原始数据帧的另一列中来实现该命令时,它将失败。

example %>% 
   mutate(counts = map(data, ~ .x %>% group_by(Time) %>%  summarise(counts = n_distinct(Chick))))
Error in eval(substitute(expr), envir, enclos) : 
  variable 'Chick' not found
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况?


我还尝试了将数据框拆分为一个列表,但没有成功。

ChickWeight %>% 
  split(.$Diet) %>% 
  map(data, ~ .x %>% group_by(Time) %>%  summarise(counts = n_distinct(Chick)))
Run Code Online (Sandbox Code Playgroud)

ali*_*ire 5

由于您在dplyr NSE中使用dplyr非标准评估,因此对于要搜索的环境感到困惑Chick。实际上,这可能是一个错误,但是可以通过开发版本的新.data代词来避免,该代词指定了查找位置:

library(tidyverse)

ChickWeight %>% 
    nest(-Diet) %>% 
    mutate(counts = map(data, 
                        ~.x %>% group_by(Time) %>% 
                            summarise(counts = n_distinct(.data$Chick))))
#> # A tibble: 4 × 3
#>     Diet               data            counts
#>   <fctr>             <list>            <list>
#> 1      1 <tibble [220 × 3]> <tibble [12 × 2]>
#> 2      2 <tibble [120 × 3]> <tibble [12 × 2]>
#> 3      3 <tibble [120 × 3]> <tibble [12 × 2]>
#> 4      4 <tibble [118 × 3]> <tibble [12 × 2]>
Run Code Online (Sandbox Code Playgroud)

要通过列表map传递它,请将第一个参数blank传递给要迭代的列表:

ChickWeight %>% 
    split(.$Diet) %>% 
    map(~ .x %>% group_by(Time) %>%  summarise(counts = n_distinct(Chick))) %>% .[[1]]

#> # A tibble: 12 × 2
#>     Time counts
#>    <dbl>  <int>
#> 1      0     20
#> 2      2     20
#> 3      4     19
#> 4      6     19
#> 5      8     19
#> 6     10     19
#> 7     12     19
#> 8     14     18
#> 9     16     17
#> 10    18     17
#> 11    20     17
#> 12    21     16
Run Code Online (Sandbox Code Playgroud)

一个更简单的选择是仅按两列进行分组:

ChickWeight %>% group_by(Diet, Time) %>% summarise(counts = n_distinct(Chick))

#> Source: local data frame [48 x 3]
#> Groups: Diet [?]
#> 
#>      Diet  Time counts
#>    <fctr> <dbl>  <int>
#> 1       1     0     20
#> 2       1     2     20
#> 3       1     4     19
#> 4       1     6     19
#> 5       1     8     19
#> 6       1    10     19
#> 7       1    12     19
#> 8       1    14     18
#> 9       1    16     17
#> 10      1    18     17
#> # ... with 38 more rows
Run Code Online (Sandbox Code Playgroud)