0

由于我在以下问题中找不到答案:

在没有显式 for 循环的情况下对组和行应用递归函数

如何模仿新行的拖动功能,例如在 Excel 中但在 R 中?

我将尝试提出与上述相关的新问题。即,我想根据先前值的输出将自定义函数按组递归地应用到当前行。

带有数据框和 for 循环的示例:

for(i in 2:nrow(df1)) df1$z[i] <- df1$z[i-1] + df1$x[i-1] - df1$y[i-1] 

带有数据框和带有自定义函数的 for 循环的示例:

for(i in 2:nrow(df1)) df1$z[i] <- ifelse(df1$z[i-1] == df1$z[i],
                                          df1$z[i-1] + df1$x[i-1] - df1$y[i-1],
                                          df1$z[i-1] - df1$x[i-1] - df1$y[i-1])

但是,对于 >1 行,data.frames 和 for 循环不是最佳的。

有没有什么办法可以用data.tableordtplyr和优化但也可以分组?

编辑: 见问题的可视化。

它应该首先像 in 一样从第二行开始for(i in 2:nrow(df),它应该使用the custom function if and only if group[i]==group[i-1] 在此处输入图像描述

4

1 回答 1

2

这种使用能解决问题Reduce吗?

tmp = data.table(
  grp = c(rep(0,6), rep(1,6)),
  x=c(10,20,30,40,50,60,1,2,3,4,5,6),
  y=c(1,2,3,4,5,6, 10,20,30,40,50,60)
)
tmp[, z:=Reduce(f=function(z,i) z + x[i-1] - y[i-1],
                x=(1:.N)[-1],
                init=0,
                accumulate = T)
    ,by=grp
]

输出:

    grp  x  y    z
 1:   0 10  1    0
 2:   0 20  2    9
 3:   0 30  3   27
 4:   0 40  4   54
 5:   0 50  5   90
 6:   0 60  6  135
 7:   1  1 10    0
 8:   1  2 20   -9
 9:   1  3 30  -27
10:   1  4 40  -54
11:   1  5 50  -90
12:   1  6 60 -135

以第 4 行为例。z 列的值为 54,等于前一行的 z 值 + 前一行的 x 值,减去前一行的 y 值。

Reduce 中的函数f可以采用任何复杂的形式,包括ifelse语句。这是一个示例,我在其中创建了一个名为 的函数func,它是Reduce. 请注意,在 Reduce 语句中,f是一个函数prev(感谢@r2evans 的建议),该函数首先计算前一行的s值减去前一行的t值(这类似于您的x[-1]-y[-1]. 然后有一个ifelse语句。如果先前的行st值(即k)> 20,则该行中的新值将是先前z值减去20-4k(即prev-(20-4k))的乘积,否则它将是先前z值+k(即等于您的原始配方z[i-1]+x[i-1]-y[i-1]:)

func <- function(s,t) {
  Reduce(
    f=function(prev,i) {
      k=s[i-1] - t[i-1]
      ifelse(k>10, prev -(20-4*k), prev+k)
    },
    x=2:length(s),
    init=0,
    accumulate = TRUE
  )
}

然后,您可以将值分配func(x,y)给 z,如下所示:

tmp[, z:=func(x,y), by=.(grp)][]

输出:

    grp  x  y    z
 1:   0 10  1    0
 2:   0 20  2    9
 3:   0 30  3   61
 4:   0 40  4  149
 5:   0 50  5  273
 6:   0 60  6  433
 7:   1  1 10    0
 8:   1  2 20   -9
 9:   1  3 30  -27
10:   1  4 40  -54
11:   1  5 50  -90
12:   1  6 60 -135
于 2022-02-24T13:58:19.663 回答