首页 > 解决方案 > R:传递多个参数来累积/减少

问题描述

这和R有关:使用上一行新生成的数据

我意识到我面临的实际问题比我在上面的线程中给出的示例要复杂一些——看来我必须将 3 个参数传递给递归计算才能实现我想要的。因此,accumulate2 或者reduce可能不起作用。所以我在这里打开一个新问题以避免可能的混淆。

我有以下按 ID 分组的数据集:

ID <- c(1, 2, 2, 3, 3, 3)
pw <- c(1:6)
add <- c(1, 2, 3, 5, 7, 8)
x <- c(1, 2, NA, 4, NA, NA)
df <- data.frame(ID, pw, add, x)

df
  ID pw add  x
1  1  1   1  1
2  2  2   2  2
3  2  3   3 NA
4  3  4   5  4
5  3  5   7 NA
6  3  6   8 NA

在 column 的每个组中x,我想保持第一行的值不变,同时用提高到存储在 中的幂的滞后值填充剩余的行pw,并将 中的值添加到指数中add。我想在继续进行时更新滞后值。所以我想拥有:

  ID pw add  x
1  1  1   1  1
2  2  2   2  2
3  2  3   3 2^3 + 3
4  3  4   5  4
5  3  5   7 4^5 + 7
6  3  6   8 (4^5 + 7)^6 + 8 

我必须将此计算应用于大型数据集,因此如果有一种快速的方法来做到这一点,那将是完美的!

标签: riterationrolling-computationaccumulate

解决方案


如果我们想使用accumulate2,那么正确地指定参数,即它需要两个输入参数作为'pw'和'add'以及一个初始化参数,它是first'x'的值。因为它是按“ID”分组的,所以在我们做之前进行分组accumulate2,提取 lambda 默认参数..1..2..3分别按该顺序并基于此创建递归函数

library(dplyr)
library(purrr)
out <- df %>%
   group_by(ID) %>% 
   mutate(x1 = accumulate2(pw[-1], add[-1], ~  ..1^..2 + ..3, 
             .init = first(x)) %>%
                flatten_dbl ) %>%
   ungroup

out$x1
#[1]    1                   2                  11   
#[4]    4                1031 1201024845477409792

如果参数超过 3 个,for循环会更好

# // initialize an empty vector
out <- c()
# // loop over the `unique` ID
for(id in  unique(df$ID)) {
    # // create a temporary subset of data based on that id
    tmp_df <- subset(df, ID == id)
     # // initialize a temporary storage output
     tmp_out <- numeric(nrow(tmp_df))
     # // initialize first value with the first element of x
     tmp_out[1] <- tmp_df$x[1]
    # // if the number of rows is greater than 1
    if(nrow(tmp_df) > 1) {
       // loop over the rows
      for(i in 2:nrow(tmp_df)) {
        #// do the recursive calculation and update
        tmp_out[i] <- tmp_out[i - 1]^ tmp_df$pw[i] + tmp_df$add[i]
        }
      } 
     
     out <- c(out, tmp_out)

}

out
#[1] 1                   2                  11     
#[4] 4                1031 1201024845477409792

推荐阅读