3

I have data

library(dplyr, warn.conflicts = FALSE)
mtcars %>% 
  as_tibble() %>% 
  select(mpg, qsec) %>% 
  head(5) %>% 
  mutate(new_col = c(10, rep(NA, times = nrow(.)-1))) 
#> # A tibble: 5 × 3
#>     mpg  qsec new_col
#>   <dbl> <dbl>   <dbl>
#> 1  21    16.5      10
#> 2  21    17.0      NA
#> 3  22.8  18.6      NA
#> 4  21.4  19.4      NA
#> 5  18.7  17.0      NA

I need a solution for new_col like mpg + qsec - lag(new_col) but with recursion.
For the second row : 21 + 17.0 - 10 = 28
For the third : 22.8 + 18.6 - 28(from second row) = 13.4

Expected output:

#> # A tibble: 5 × 3
#>     mpg  qsec new_col
#>   <dbl> <dbl>   <dbl>
#> 1  21    16.5    10  
#> 2  21    17.0    28  
#> 3  22.8  18.6    13.4
#> 4  21.4  19.4    27.4
#> 5  18.7  17.0     8.3
user438383
  • 5,716
  • 8
  • 28
  • 43
jyjek
  • 2,627
  • 11
  • 23
  • Does this answer your question? [Recursive function using dplyr](https://stackoverflow.com/questions/48868104/recursive-function-using-dplyr) – harre Jul 13 '22 at 12:22

2 Answers2

4

You can use purrr::accumulate() (or base::Reduce() if you prefer):

library(dplyr)
library(purrr)

mtcars %>% 
  as_tibble() %>% 
  select(mpg, qsec) %>% 
  head(5) %>% 
  mutate(new_col = accumulate(tail(mpg + qsec, -1), .f = ~ .y - .x, .init = 10))

# A tibble: 5 × 3
    mpg  qsec new_col
  <dbl> <dbl>   <dbl>
1  21    16.5   10   
2  21    17.0   28.0 
3  22.8  18.6   13.4 
4  21.4  19.4   27.4 
5  18.7  17.0    8.27
Ritchie Sacramento
  • 29,890
  • 4
  • 48
  • 56
2

Another possible solution, using purrr::reduce:

library(tidyverse)

df %>% 
  transmute(reduce(2:n(), ~ {.x$new_col[.y] <- (.x$mpg[.y] + .x$qsec[.y] - 
    .x$new_col[.y-1]); .x}, .init = .))

#> # A tibble: 5 × 3
#>     mpg  qsec new_col
#>   <dbl> <dbl>   <dbl>
#> 1  21    16.5   10   
#> 2  21    17.0   28.0 
#> 3  22.8  18.6   13.4 
#> 4  21.4  19.4   27.4 
#> 5  18.7  17.0    8.27
PaulS
  • 21,159
  • 2
  • 9
  • 26