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)
CodePudding user response:
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
CodePudding user response:
I prefer the Reduce()
way. Here is an attempt to incorporate a loop into mutate()
.
a %>%
mutate(across(, ~ {
for(i in 2:length(.x)) {
.x[i] <- .x[i - 1] .x[i] * (1 - .x[i - 1])
}; .x
}))
# # 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