R:递归添加行

HCA*_*CAI 3 r accumulate dplyr rolling-computation purrr

j 个表面接触后手部细菌的浓度可以由以下递归关系决定:

H[j+1]=H[j]+T[j]*(S[j]-H[j])
Run Code Online (Sandbox Code Playgroud)

S手触摸的表面浓度在哪里(为了方便,假设是随机的)。T是每个接触的传输效率。我想计算最终的手部浓度(起始浓度为零)。

我有一个数据框,它有一个表面接触向量和每个表面的传输效率。我有两个组a&b并且在每个组中假设我将依次触摸每个组1:length(df)

 df <- data.frame(S = runif(10)*100, T = runif(10),g=rep(c("a","b"),each=5))
Run Code Online (Sandbox Code Playgroud)

我想在可能的情况下计算H按组计算的累积总和dplyr

一个特例:

如果g = "a", 的起始值H0。如果g=="b"那么的起始值H是从何时开始的最后一个值g=="a"

Ani*_*yal 5

为了完整起见并从 Arun 和 Onyambu 那里获取线索(在一个单独的问题上),我也在此处添加 baseR 答案。

transform(df, H = Reduce(function(.x, .y) .x + df$T[.y] * (df$S[.y] - .x) * !c(!duplicated(df$g)[-1], 0)[.y],
                         seq(nrow(df)),
                         init = 0,
                         accumulate = TRUE)[-(1 + nrow(df))])

           S         T g        H
1  37.698250 0.8550377 a  0.00000
2   3.843585 0.4722659 a 32.23342
3  33.150788 0.3684791 a 18.82587
4   8.948116 0.8893603 a 24.10430
5  57.061844 0.5452377 a 10.62499
6  49.648827 0.7719067 b 10.62499
7  95.403697 0.5835950 b 40.74775
8  10.598677 0.1220491 b 72.64469
9  91.913365 0.2166443 b 65.07203
10 69.644200 0.2603413 b 70.88705
Run Code Online (Sandbox Code Playgroud)

较早的回答 我朋友的回答略有不同,我希望可以达到您的目的。我唯一的假设是您的数据已经按组排序a并排在前面b(完全如示例中所示)。既然你没有给随机种子,我也拿了我朋友拿的同样的数据。

  • 策略/黑客,我使用0T内部accumulate2参数的值,以便H在组的a第一个值中重复组中的最后一个值b
transform(df, H = Reduce(function(.x, .y) .x + df$T[.y] * (df$S[.y] - .x) * !c(!duplicated(df$g)[-1], 0)[.y],
                         seq(nrow(df)),
                         init = 0,
                         accumulate = TRUE)[-(1 + nrow(df))])

           S         T g        H
1  37.698250 0.8550377 a  0.00000
2   3.843585 0.4722659 a 32.23342
3  33.150788 0.3684791 a 18.82587
4   8.948116 0.8893603 a 24.10430
5  57.061844 0.5452377 a 10.62499
6  49.648827 0.7719067 b 10.62499
7  95.403697 0.5835950 b 40.74775
8  10.598677 0.1220491 b 72.64469
9  91.913365 0.2166443 b 65.07203
10 69.644200 0.2603413 b 70.88705
Run Code Online (Sandbox Code Playgroud)

reprex 包( v2.0.0 )于 2021 年 7 月 10 日创建

  • 当堆栈允许我时,我想为您提供赏金。谢谢你的帮助! (2认同)
  • @HCAI,为那里的一个小错误编辑了较早的答案(以前我剪的是倒数第二个值,而不是预期的最后一个值)。另外,我还添加了一个 BaseR 策略来处理在“accumulate/Reduce”系列中具有多个输入的案例,这是我从我的朋友 Anoushiravan 和 Onyambu 那里学到的 (2认同)

akr*_*run 5

这是@AnilGoyal 针对一般情况展示的类似方法

library(dplyr)
library(purrr)
df %>%
    mutate(H = accumulate2(S, T* !lead(!duplicated(g), default = FALSE),
          .init = 0, ~ ..1 + ..3 * (..2 - ..1))[-n()])
Run Code Online (Sandbox Code Playgroud)

  • 你们用黑魔法解决了这个问题,而我是一个简单的凡人:) (3认同)
  • 聪明的黑客亲爱的@akrun!点赞 (2认同)
  • 这是我刚刚调整的 AnilGoyal 的魔法。 (2认同)