如何使用accumulate函数来计算2个相互交织的变量

How to use accumulate function to calculate 2 intertwining variables

亲爱的朋友/老师/各位R用户,大家好,

一段时间以来,我一直在考虑使用 purrr 中的 accumulate 函数族,最近我遇到了一个非常棘手的情况,我们想计算 2 个新函数每一行的变量,我们必须使用另一行来计算每一行。这是我的数据集(这是我看到的另一个问题的摘录):

structure(list(Scenario = c(0, 1, 1, 1, 1, 1, 1, 1, 1, 1), SlNo = c(NA, 
1L, 5L, 9L, 13L, 17L, 21L, 25L, 29L, 33L), A = c(NA, 14, 1, 17, 
8, 10, 9, 14, 14, 4), B = c(NA, 19, 13, 20, 7, 16, 12, 18, 15, 
17), C = c(4, 0, 0, 0, 0, 0, 0, 0, 0, 0), E = c(6, 0, 0, 0, 0, 
0, 0, 0, 0, 0)), row.names = c(NA, -10L), class = c("tbl_df", 
"tbl", "data.frame"))

我想要的输出是这样的:

   Scenario  SlNo     A     B     C      E
      <dbl> <int> <dbl> <dbl> <dbl>  <dbl>
 1        0    NA    NA    NA   4     6   
 2        1     1    14    19  32     1   
 3        1     5     1    13  35    -2   
 4        1     9    17    20  40.5  10.5 
 5        1    13     8     7  42.8  -0.25
 6        1    17    10    16  42.1   8.12
 7        1    21     9    12  46.2   8.19
 8        1    25    14    18  54.3  22.3 
 9        1    29    14    15  69.4  34.4 
10        1    33     4    17  91.1  58.1

我们当然可以使用for循环来计算从第二行到最后一行的变量CE的值。这样做的好处是我可以在每次迭代中同时填充两个变量,例如使用 E 的当前值来计算 C 的当前值,反之亦然:

for(i in 2:nrow(df)) {

df$C[i] <- if_else(df$Scenario[i] != 0, (1-0.5) * df$C[i-1] + 3 + 2 + df$B[i] + df$E[i-1],
              df$C[i])
df$E[i] <- if_else(df$Scenario[i] != 0, df$C[i] + df$B[i] - 50, df$E[i])

}

df

所以我很感激 accumulate 有一些关于如何将它应用到这类问题的解决方案。

非常感谢您

在这种情况下,我们需要同时生成两个输出列;并在一个输入列的帮助下迭代并给定两个输出列的两个初始值。现在,purrr::accumulate 通常基于一个输入在一个输出上工作,而 purrr::accumulate2() 在 2 个输入上再次工作一个输出。因此,相反,我的累积策略详述如下:-

为了进一步参考,您可能还会看到此 answerpurrr::accumulate 中同时使用甚至超过 2 个参数(输入值)生成了多个结果

  • 我假设您的第一行只是在列的剩余值中输入 first/initial 值。
  • 要在 accumulate 中有多个输出,您可以使这个函数 purrr::accumulate (我必须说是很棒的函数)作为生成小标题而不是向量。
  • 我删除了第一行。
  • .init 参数中使用了您的初始值
  • 创建了 tibble 格式的输出
  • 使用的语法tibble(C = (1 -0.5)* .x$C + 5 + .y + .x$E, E = 0.5 * .x$C + 5 + .x$E + 2 * .y - 50)
  • 如果仔细观察,C 是用给定的公式生成的。但是,
  • 对于 E 我们需要生成(输出)值 C 因此,我使用 C 的公式而不是使用 .x.y
  • 最后,使用 unnest_widertidyr
  • 中取消嵌套输出
library(tidyverse, warn.conflicts = F)

df <- structure(list(Scenario = c(0, 1, 1, 1, 1, 1, 1, 1, 1, 1), SlNo = c(NA, 
                                                                          1L, 5L, 9L, 13L, 17L, 21L, 25L, 29L, 33L), A = c(NA, 14, 1, 17, 
                                                                                                                           8, 10, 9, 14, 14, 4), B = c(NA, 19, 13, 20, 7, 16, 12, 18, 15, 
                                                                                                                                                       17), C = c(4, 0, 0, 0, 0, 0, 0, 0, 0, 0), E = c(6, 0, 0, 0, 0, 
                                                                                                                                                                                                       0, 0, 0, 0, 0)), row.names = c(NA, -10L), class = c("tbl_df", 
                                                                                                                                                                                                                                                           "tbl", "data.frame"))

df[1:4] %>%
  filter(Scenario != 0) %>%
  mutate(new = accumulate(B, 
                          .init = tibble(C = 4, E = 6),
                          ~ tibble(C = (1 -0.5)* .x$C + 5 + .y + .x$E,
                                   E = 0.5 * .x$C + 5 + .x$E + 2 * .y - 50
                                   )
                          )[-1]
         ) %>% 
  unnest_wider(new)
#> # A tibble: 9 x 6
#>   Scenario  SlNo     A     B     C     E
#>      <dbl> <int> <dbl> <dbl> <dbl> <dbl>
#> 1        1     1    14    19  32    1   
#> 2        1     5     1    13  35   -2   
#> 3        1     9    17    20  40.5 10.5 
#> 4        1    13     8     7  42.8 -0.25
#> 5        1    17    10    16  42.1  8.12
#> 6        1    21     9    12  46.2  8.19
#> 7        1    25    14    18  54.3 22.3 
#> 8        1    29    14    15  69.4 34.4 
#> 9        1    33     4    17  91.1 58.1

reprex package (v2.0.0)

于 2021-07-05 创建

这是一个 base R 解决方案:

df[, c("C", "E")] <- do.call(rbind, Reduce(function(x, y) {
  data.frame(C = 0.5 * x[["C"]] + 5 + df$B[y] + x[["E"]],
             E = 0.5 * x[["C"]] + 5 + df$B[y] + x[["E"]] + df$B[y] - 50)
}, init = data.frame(C = 4, E = 6), 2:nrow(df), accumulate = TRUE))

df

# A tibble: 10 x 6
   Scenario  SlNo     A     B     C     E
      <dbl> <int> <dbl> <dbl> <dbl> <dbl>
 1        0    NA    NA    NA   4    6   
 2        1     1    14    19  32    1   
 3        1     5     1    13  35   -2   
 4        1     9    17    20  40.5 10.5 
 5        1    13     8     7  42.8 -0.25
 6        1    17    10    16  42.1  8.12
 7        1    21     9    12  46.2  8.19
 8        1    25    14    18  54.3 22.3 
 9        1    29    14    15  69.4 34.4 
10        1    33     4    17  91.1 58.1