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

Implementing map() on a column of nested data frames

我正在自学 R tidyverse purr() 包,但在对一列嵌套数据框实施 map() 时遇到了问题。有人可以解释一下我错过了什么吗?

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

library(tidyverse) 
ChickWeight %>%
  filter(Diet == 1) %>% 
  group_by(Time) %>% 
  summarise(counts = n_distinct(Chick))

这很好,但我想一次为每种饮食做这件事,我认为嵌套数据并用 map() 迭代它是一个很好的方法。 这就是我所做的:

example <- ChickWeight %>% 
  nest(-Diet) 

实现这个地图函数就实现了我的目标:

map(example$data, ~ .x %>% group_by(Time) %>% summarise(counts = n_distinct(Chick))) 

然而,当我尝试使用管道实现相同的命令以将其放入原始数据框的另一列时,它失败了。

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

为什么会出现这种情况?


我也在dataframe拆分成list上试过,没用。

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

因为您在 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]>

要将其通过列表传递,请将 map 的第一个参数留空以传递要迭代的列表:

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

一个更简单的选择是只按两列分组:

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