首页 文章

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

提问于
浏览
1

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

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

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

我期望的是每个组的tbl,每年的结果列表:

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

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

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

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

1 回答

  • 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
    

相关问题