使用嵌套数据框访问purrr :: map()中的分组变量

时间:2018-12-19 16:57:33

标签: r dplyr tidyr purrr

我将tidyr::nest()purrr::map()(家族)结合使用,将data.frame分组,然后对每个子集做一些花哨的东西。考虑以下示例,请忽略以下事实:我不需要nest()map()来这样做(这是一个简化的示例):

library(dplyr)
library(purrr)
library(tidyr)

mtcars %>% 
  group_by(cyl) %>%
  nest() %>%
  mutate(
    wt_mean = map_dbl(data,~mean(.x$wt))
  )

# A tibble: 8 x 4
    cyl  gear data               cly2
  <dbl> <dbl> <list>            <dbl>
1     6     4 <tibble [4 x 9]>      6
2     4     4 <tibble [8 x 9]>      4
3     6     3 <tibble [2 x 9]>      6
4     8     3 <tibble [12 x 9]>     8
5     4     3 <tibble [1 x 9]>      4
6     4     5 <tibble [2 x 9]>      4
7     8     5 <tibble [2 x 9]>      8
8     6     5 <tibble [1 x 9]>      6

通常,当我执行此类操作时,需要访问cyl中的分组变量(在这种情况下为map())。但是这些分组变量显示为向量,其长度与嵌套数据框中的行数相对应,因此不易使用。

有没有一种方法可以运行以下操作?我希望将wt的均值除以圆柱数(cyl)每组(即行)。

mtcars %>% 
  group_by(cyl,gear) %>%
  nest() %>%
  mutate(
    wt_mean = map_dbl(data,~mean(.x$wt)/cyl)
  )


Error in mutate_impl(.data, dots) : 
  Evaluation error: Result 1 is not a length 1 atomic vector.

2 个答案:

答案 0 :(得分:3)

cyl通话中删除map

mtcars %>% 
  group_by(cyl,gear) %>%
  nest() %>%
  mutate(
    wt_mean = map_dbl(data, ~mean(.x$wt)) / cyl
  )

# A tibble: 8 x 4
    cyl  gear data              wt_mean
  <dbl> <dbl> <list>              <dbl>
1     6     4 <tibble [4 x 9]>    0.516
2     4     4 <tibble [8 x 9]>    0.595
3     6     3 <tibble [2 x 9]>    0.556
4     8     3 <tibble [12 x 9]>   0.513
5     4     3 <tibble [1 x 9]>    0.616
6     4     5 <tibble [2 x 9]>    0.457
7     8     5 <tibble [2 x 9]>    0.421
8     6     5 <tibble [1 x 9]>    0.462

map_dblcyl视为长度为8的向量,因为nestdata.frame中删除了组。在cyl函数调用中使用map_*(如OP的示例)会产生8个长度为8的向量。

其他2种方法:

两者均具有与上述相同的结果,但根据OP的规范,将分组的变量保留在map_*调用中:

nest之后重新分组

mtcars %>% 
  group_by(cyl,gear) %>%
  nest() %>%
  group_by(cyl, gear) %>%
  mutate(wt_mean = map_dbl(data,~mean(.x$wt)/cyl))

map2用于遍历cyl

mtcars %>% 
  group_by(cyl,gear) %>%
  nest() %>%
  mutate(wt_mean = map2_dbl(data, cyl,~mean(.x$wt)/ .y))

答案 1 :(得分:0)

dplyr 0-8-0的新版本中,您现在可以使用group_map,对于这种用例,我发现它非常方便。这是github用户@yutannihilation的the example

library(dplyr, warn.conflicts = FALSE)

mtcars %>% 
  group_by(cyl) %>%
  group_map(function(data, group_info) {
    tibble::tibble(wt_mean = mean(data$wt) / group_info$cyl)
  })