如何使用purr的映射函数计算嵌套列表列中特定列的平均值/总和

时间:2019-10-05 18:30:34

标签: r tidyverse purrr

我正在尝试使用purr来汇总嵌套列表列的特定列。

library(tidyverse)
z <- tibble(name = c("Bill","Bill","Bill","Sue","Sue"), grade =c(90L,95L,70L,100L,98L), time=c(10L,11L,10L,15L,16L))

summary <- z %>% 
  group_by(name) %>% 
  nest %>% 
  mutate(n = map_int(data,nrow)) %>% 
  mutate(avg = map(data$grade,mean)) %>% 
  mutate(ttl_time = map(data$time, sum))

运行此命令时出现错误::列y的长度必须为3(行数)或1,而不是2

我的目标输出是:

name      data     n      avg      ttl_time

Bill     [3x3]     3      92        31

Sue      [2x3]     2      99        31  

当我删除最后两个mutate函数时,脚本将按预期工作。这使我相信我没有在数据列中隔离等级和时间列,但是我可以弄清楚我做错了什么?

我观看了这个r工作室视频,我相信自己正在做的事情与我在视频中看到的一样。 Working with List Columns

1 个答案:

答案 0 :(得分:0)

z %>% 
  group_by(name) %>% 
  nest() %>% 
  mutate(n = map_int(data, nrow),
         avg = map_dbl(data, ~ mean(.x$grade)),
         ttl_time = map_dbl(data, ~ sum(.x$time)))

# # A tibble: 2 x 5
#   name  data                 n   avg ttl_time
#   <chr> <list>           <int> <dbl>    <dbl>
# 1 Bill  <tibble [3 × 2]>     3    85       31
# 2 Sue   <tibble [2 × 2]>     2    99       31

带有~的公式表示法是例如function(.x) mean(.x$grade)


OP的错误确实是由于map无法直接在grade列表的每个data元素上进行迭代这一事实,至少不是使用这种语法。

data$grade被理解为列表data中名称为grade的元素,并且没有这样的元素。

这种替代语法可能有助于了解如何实现:

z %>% 
  group_by(name) %>% 
  nest() %>% 
  mutate(n = map_int(data, nrow),
         avg = map_dbl(map(data, "grade"), mean),
         ttl_time = map_dbl(map(data, "time"), sum))

其中map(data, "grade")从列表列grade的元素中提取每个data组件。

虽然我认为这比第一个建议的可读性差。