矢量化循环两行与条件

时间:2018-03-16 13:24:58

标签: r for-loop vectorization

我想在我的数据帧上执行一些操作,但是我在性能方面遇到了一些问题,所以我想知道如何加快代码的性能。 我的数据有几列,如果列X为0,我想对其他列进行一些操作(添加和最大)。如果X为1,则不执行任何操作(X只能为1或0)

df <- data.frame(X = c(0,0,1,0,1),Y = c(10,0,0,3,7),Z = c(2,2,0,4,5)) 


   df
  X  Y Z
1 0 10 2
2 0  0 2
3 1  0 0
4 0  3 4
5 1  7 5

现在我的代码看起来像:

for(i in 1:(nrow(df)-1)){
  if(df$X[i] == 0){
    df$Y[i+1] <- df$Y[i]+df$Y[i+1]
    df$Z[i+1] <- max(df$Z[i],df$Z[i+1])
  }
}

结果如下:

df
  X  Y Z
1 0 10 2
2 0 10 2
3 1 10 2
4 0  3 4
5 1 10 5

有没有办法更有效地写这个? 另外,很多行只包含0,所以我想知道是否有一种有效的方法可以跳过这些行的操作,因为值不会改变。

编辑: 由于我对规则有点不明确,所以在这里它们更详细: Y应该总结直到再次有1(总和(包括行的值,其中1是)应该用1替换行的值。同样的原则应该应用于X变量,但这次使用max()函数。

非常感谢!

1 个答案:

答案 0 :(得分:1)

这样的事情怎么样?这将再现您的预期输出:

df <- data.frame(X = c(0,0,1,0,1),Y = c(10,0,0,3,7),Z = c(2,2,0,4,5))

df %>%
    mutate(
        group = cumsum(c(0, diff(X) == -1))) %>%
    group_by(group) %>%
    mutate(
        n = 1:n(),
        Y = cumsum(Y),
        Z = ifelse(n > 1, max(Z, lead(Z, default = 0)), Z)) %>%
    ungroup() %>%
    select(X, Y, Z)
#    # A tibble: 5 x 3
#      X     Y     Z
#  <dbl> <dbl> <dbl>
#1    0.   10.    2.
#2    0.   10.    2.
#3    1.   10.    2.
#4    0.    3.    4.
#5    1.   10.    5.

说明:基于0的群组条目 - 由1终止的系列;将Y替换为cumsum的{​​{1}};将Y替换为该行中的最大条目,并从第二行(Z)开始替换下一行。