R- 在 cumsum 函数中包含起点

R- Include starting point in cumsum function

我有这个data.frame:

       a b
 [1,]  1 0
 [2,]  2 0
 [3,]  3 0
 [4,]  4 0
 [5,]  5 0
 [6,]  6 1
 [7,]  7 2
 [8,]  8 3
 [9,]  9 4
[10,] 10 5

我想在 column a 上应用 cumsum 仅当其在 column b 上的对应值不同于 0 时。

我在下面尝试了这个,但它不包括 cumsum 的起始条件:

   df_cumsum <- cbind(c(1:10), c(0,0,0,0,0,1,2,3,4,5),
                       as.data.frame(ave(A[,1], A[,2] != 0, FUN=cumsum)))

不幸的是,我在整个专栏中获得了 cumsum

    a b  c
1   1 0  1
2   2 0  3
3   3 0  6
4   4 0 10
5   5 0 15
6   6 1  6
7   7 2 13
8   8 3 21
9   9 4 30
10 10 5 40

我想获得:

    a b  c
1   1 0  0
2   2 0  0
3   3 0  0
4   4 0  0
5   5 0  0
6   6 1  6
7   7 2 13
8   8 3 21
9   9 4 30
10 10 5 40

感谢您的帮助!

最好建立索引更新

i1 <- df1$b > 0
df1$c[i1] <- with(df1, cumsum(a[i1]))

或单行

df1$c <- with(df1, cumsum(a * (b > 0)))
df1$c
#[1]  0  0  0  0  0  6 13 21 30 40

假设输入是 df,如末尾的注释中所示,试试这个。它会将 b 为 0 的任何 a 值清零。

transform(df, cum = cumsum((b > 0) * a))

给予:

    a b cum
1   1 0   0
2   2 0   0
3   3 0   0
4   4 0   0
5   5 0   0
6   6 1   6
7   7 2  13
8   8 3  21
9   9 4  30
10 10 5  40

备注

我们假设此输入以可重现的形式显示:

Lines <- "
  a b
  1 0
  2 0
  3 0
  4 0
  5 0
  6 1
  7 2
  8 3
  9 4
 10 5"
df <- read.table(text = Lines, header = TRUE)

更新

ab 被颠倒了。已修复。

我真的很喜欢其他答案使用 a * (b > 0) 的简洁程度,但这有时会让新手程序员有点困惑。作为此语法的替代方法,您可以使用矢量化 ifelse 函数。

df <- data.frame(a=c(1:10), b=c(0,0,0,0,0,1,2,3,4,5))
# One way
df$c <- cumsum(ifelse(df$b>0,df$a,0))
# Another way
df$d <- with(df,cumsum(ifelse(b>0,a,0)))