R:传递多个参数来累加/减少

dia*_*iii 5 iteration r accumulate rolling-computation

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

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

我有以下按 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
Run Code Online (Sandbox Code Playgroud)

在列的每个组中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 
Run Code Online (Sandbox Code Playgroud)

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

akr*_*run 7

如果我们想使用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
Run Code Online (Sandbox Code Playgroud)

如果参数超过 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
Run Code Online (Sandbox Code Playgroud)


Ano*_*n R 5

基础 R 中,我们可以对两个以上的参数使用以下解决方案。

  • 在这个解决方案中,我首先对ID值的原始数据集进行子集
  • 然后我通过seq_len(nrow(tmp))[-1]省略第一行 id来选择行 id 值,因为它是由init
  • 在我使用的匿名函数中Reduceb参数表示累积/以前的值,从我们的向量开始initc表示新/当前值,即行号
  • 因此,在每次迭代我们以前的值(从开始init)将提高到新的价值的力量来自pw并将由新的价值可以概括add
cbind(df[-length(df)], unlist(lapply(unique(df$ID), function(a) {
  tmp <- subset(df, df$ID == a)
  Reduce(function(b, c) {
    b ^ tmp$pw[c] + tmp$add[c]
  }, init = tmp$x[1],
  seq_len(nrow(tmp))[-1], accumulate = TRUE)
}))) |> setNames(c(names(df)))

  ID pw add            x
1  1  1   1 1.000000e+00
2  2  2   2 2.000000e+00
3  2  3   3 1.100000e+01
4  3  4   5 4.000000e+00
5  3  5   7 1.031000e+03
6  3  6   8 1.201025e+18
Run Code Online (Sandbox Code Playgroud)

数据

structure(list(ID = c(1, 2, 2, 3, 3, 3), pw = 1:6, add = c(1, 
2, 3, 5, 7, 8), x = c(1, 2, NA, 4, NA, NA)), class = "data.frame", row.names = c(NA, 
-6L))
Run Code Online (Sandbox Code Playgroud)