通过group_by在dplyr :: do()上应用增量函数

时间:2018-04-26 07:23:51

标签: r dplyr

在计算序列的增量结果时,我很难通过group_by应用dplyr :: do()。

在一个简单的情况下,我可以使用for-loop:

df <- data.frame(year = rep(2000:2002, 1), id = rep(letters[1], 3), obs1 = rep(1,3), obs2 = rep(1,3))

initialValue <- 5

for(i in 1:nrow(df)){
initialValue[i+1] <- initialValue[i] + df$obs1[i] + df$obs1[i] 
}

因此,输出是初始值,后跟列表中2000年:2002年的更新值:

> initialValue
[1]  5  7  9 11

但是我有几年的数据和几个组(ID)。我相信dplyr :: do()就是答案:

library(dplyr)

df <- data.frame(year = rep(2000:2002, 3), id = rep(letters[1:3], 3), obs1 = rep(1,9), obs2 = rep(1,9))
initialValue <- 5

doCalc <- function(obs){
initialValue <- initialValue + sum(obs)
}

df %>%
  group_by(id) %>%
  do(new <- doCalc(obs = c(.$obs1, .$obs2)))

错误:

Error: Results 1, 2, 3 must be data frames, not numeric

我期望每个小组都有一个每年的结果列表:

[[1]]
[1]  5  7  9 11

[[2]]
[1]  5  7  9 11

[[3]]
[1]  5  7  9 11

那么如何在函数中递增地应用它?

1 个答案:

答案 0 :(得分:0)

我们可以使用accumulate

中的purrr
library(tidyverse)
df %>%
   group_by(id) %>% #assuming many groups are found in the original data
   mutate(val = list(accumulate(obs1, ~ .x + 2 *.y, .init = initialValue))) %>% 
  .$val
#[[1]]
#[1]  5  7  9 11

#[[2]]
#[1]  5  7  9 11

#[[3]]
#[1]  5  7  9 11

或者我们可以使用Reduce

中的base R
unsplit(lapply(split(df, df$id), function(dat)  {
   dat$val <- list(Reduce(function(x, y) x + 2 *y, dat$obs1,
              accumulate = TRUE, init = initialValue))
   dat}), df$id)

数据

df <- data.frame(year = rep(2000:2002, 1), id = rep(letters[1], 3), 
           obs1 = rep(1,3), obs2 = rep(1,3))
initialValue <- 5