迭代数据帧,其中每次迭代有效地依赖于R中的前一项

Geo*_*rge 7 iteration r vectorization purrr tidyverse

我有一个数据框,有两个长度为5和变量的向量:

x <- seq(1:5)
y <- rep(0,5)
df <- data.frame(x, y)
z <- 10
Run Code Online (Sandbox Code Playgroud)

我需要遍历数据帧并根据与x相关的条件使用z更新y,并且我需要在每次迭代时更新z.使用for循环,我会这样做:

for (i in seq(2,nrow(df))){
  if(df$x[i] %% 2 == 0){
    df$y[i] <- df$y[i-1] + z
    z <- z - df$x[i]
  } else{
    df$y[i] <- df$y[i-1]
  }
}
Run Code Online (Sandbox Code Playgroud)

使用数据帧很慢并且必须使用df $ x [i]访问第i个项目效率不高,但我不确定如何对其进行向量化,因为y和z都会根据每次迭代而改变.

有没有人有关于迭代这个的最佳方法的建议?我想完全避免使用数据帧,只是使用向量来简化查找,或者使用tidyverse和purrr包使用tidyverse,但似乎没什么好容易实现的.谢谢!

Ony*_*mbu 5

你可以使用sapply功能:

y=0
z=10
sapply(df$x,function(x)ifelse(x%%2==0,{y<<-y+z;z<<-z-x;y},y<<-y))
[1]  0 10 10 18 18
Run Code Online (Sandbox Code Playgroud)


jay*_*.sf 2

由于您的数据仅包含数字,因此您可以使用矩阵而不是速度稍快的数据框。

mx <- matrix(c(x, y), ncol = 2, dimnames = list(1:length(x), c("x", "y")))

for (i in seq(2, nrow(mx))){
  if(mx[i, 1] %% 2 == 0){
    mx[i, 2] <- mx[i-1, 2] + z
    z <- z - mx[i, 1]
    } else {
      mx[i, 2]  <- mx[i-1, 2] 
    }
  }

mx
# x  y
# 1 1  0
# 2 2 10
# 3 3 10
# 4 4 18
# 5 5 18
Run Code Online (Sandbox Code Playgroud)

microbenchmark()结果:

# Unit: milliseconds
#  expr       min        lq     mean    median       uq       max neval
#    mx  8.675346  9.542153 10.71271  9.925953 11.02796  89.35088  1000
#    df 10.363204 11.249255 12.85973 11.785933 13.59802 106.99920  1000
Run Code Online (Sandbox Code Playgroud)