使用 dplyr 对两个变量进行递归求和

C. *_*ian 6 recursion performance r dataframe dplyr

我有两列带有值 a 和 b。我想添加第三列c,即(在第i行)b的0到i的总和加上c的0到(i-1)的总和,乘以a,即

c_i = (sum_i (b) + sum_(i-1) (c) ) * a_i
Run Code Online (Sandbox Code Playgroud)

我试过

data %>%
mutate(
 c = a * (cumsum(b) + lag(cumsum(c), default = 0))
)
Run Code Online (Sandbox Code Playgroud)

但是这不起作用,因为我只是根据目前不存在的 c 值创建 c :

Error: Problem with `mutate()` input `c`.
x object 'c' not found
Run Code Online (Sandbox Code Playgroud)

以前我使用 for 循环处理此类问题。不过,我习惯了dplyr,总有办法。但是,我不明白。

我很感激任何帮助!

编辑:在以前的版本中我是不准确的,因为 a 也是一个向量,而不是一个常数。我在公式里改了

所需的输出:

row 1: 0.5 * (7  + 0 ) =3.5

row 2: 0.3 * (7+1 + 3.5) = 3.45

row 3: 1.0 * (7+1+9 + 3.5+3.45) = 23.95

| a | b | c |
|---|---|---|
|0.5|7|3.5|
|0.3|1|3.45|
|1|9|23.95|
|0.2|10|...|
Run Code Online (Sandbox Code Playgroud)

Ani*_*yal 4

也许我会像@27phi9那样以类似的方式做到这一点。但是,您可以在不事先编写任何函数的情况下执行此操作。我给你三种方法(i)baseR,(ii)仅 dplyr,(iii)dplyr + purrr

df <- structure(list(a = c(0.5, 0.3, 1, 0.2, 0.4, 0.8), b = c(7L, 1L,  9L, 10L, 3L, 2L)), row.names = c(NA, -6L), class = c("tbl_df",  "tbl", "data.frame"))

transform(df, C = {x <- 0; Reduce(function(.x, .y){x <<- .x + x; (cumsum(b)[[.y]] + x) * a[[.y]]}, 
                                  seq(nrow(df)), 
                                  init = 0, 
                                  accumulate = TRUE)[-1]})
#>     a  b       C
#> 1 0.5  7  3.5000
#> 2 0.3  1  3.4500
#> 3 1.0  9 23.9500
#> 4 0.2 10 11.5800
#> 5 0.4  3 28.9920
#> 6 0.8  2 82.7776
Run Code Online (Sandbox Code Playgroud)
library(dplyr)

df %>%
  mutate(C = {x <- 0; Reduce(function(.x, .y){x <<- .x + x; (cumsum(b)[[.y]] + x) * a[[.y]]}, 
                             seq(nrow(df)), 
                             init = 0, 
                             accumulate = TRUE)[-1]})
#> # A tibble: 6 x 3
#>       a     b     C
#>   <dbl> <int> <dbl>
#> 1   0.5     7  3.5 
#> 2   0.3     1  3.45
#> 3   1       9 24.0 
#> 4   0.2    10 11.6 
#> 5   0.4     3 29.0 
#> 6   0.8     2 82.8
Run Code Online (Sandbox Code Playgroud)
library(purrr)
df %>%
  mutate(C = {x <- 0; unlist(accumulate2(cumsum(b), a, .init = 0, ~ {x <<- ..1 + x; (..2 + x) * ..3 }))[-1]})
#> # A tibble: 6 x 3
#>       a     b     C
#>   <dbl> <int> <dbl>
#> 1   0.5     7  3.5 
#> 2   0.3     1  3.45
#> 3   1       9 24.0 
#> 4   0.2    10 11.6 
#> 5   0.4     3 29.0 
#> 6   0.8     2 82.8
Run Code Online (Sandbox Code Playgroud)