用dplyr的across/rowwise替换for循环?

3

我正在尝试将一个for循环重构为dplyr管道,但我遇到了困难。 我需要引用数据框a和之前计算的行。 有什么建议可以在dplyr管道中从a获得b吗?

非常感谢!

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)


2个回答

1
你可以使用Reduce()(或者如果你更喜欢,purrr::accumulate())来实现。
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

1

我更喜欢使用Reduce()方法。这里尝试将循环嵌入到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

这很有趣 - 我真的没有想过那个 :) - cg1979

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接