Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

replace for loop with dplyr across / rowwise?

I'm having a hard time refactoring a for loop into a dplyr pipe. I need to reference the dataframa a and the previously calculated row. Any advice how to get b from a on a dplyr pipe?

Many thanks!

a <- tibble::tribble(~ 'a',  ~ 'b',  ~ 'c',
                     .1, .2, .3,
                     .2, .4, .6,
                     .3, .6, .9)
b <- a

for (i in 2:nrow(a)) {
  b[i, ] <- b[i - 1, ] + b[i, ] * (1 - b[i - 1, ])
}


c <- a |>
  dplyr::mutate(dplyr::across(where(is.numeric),
                              ~ dplyr::lag(.x, 1, 0) +
                                .x *
                                (1 - dplyr::lag(.x, 1, 0))))

d <- a |> dplyr::rowwise( )|>
  dplyr::mutate(dplyr::across(where(is.numeric),
                              ~ dplyr::lag(.x, 1, 0) +
                                .x *
                                (1 - dplyr::lag(.x, 1, 0))))
identical(b,c)
identical(b,d)


like image 527
cg1979 Avatar asked Dec 19 '25 18:12

cg1979


1 Answers

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

library(dplyr)

a |>
  mutate(across(where(is.numeric), \(v) Reduce(\(x, y) x + y * (1 - x) , v, accumulate = TRUE)))

# A tibble: 3 × 3
      a     b     c
  <dbl> <dbl> <dbl>
1 0.1   0.2   0.3  
2 0.28  0.52  0.72 
3 0.496 0.808 0.972
like image 139
Ritchie Sacramento Avatar answered Dec 21 '25 08:12

Ritchie Sacramento



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!