条件累积和

时间:2011-12-16 17:18:18

标签: r

我有这个数据框

t<-data.frame(v1=c(1,2,1,4,6,7,8,2,3,4,8,1,2), v2=c(2,3,6,1,-3,-2,1,2,-3,6,7,-2,1))

从上到下扫描data.frame,只要v2为正,我想获得v1的累积和。当v2变为负数时,它应该停止,记录(到那时为止的cum.sum)的值,并且累计和应该从下一个第一个正v2重新开始,依此类推。因此,最终对于上述数据框将是向量

8, 10 , 12, 2

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

我更改了data.frame的名称,因为t是一个函数(转置)。如果你只想要总和,我不明白你为什么要使用cumsum。

dtf<-data.frame(v1=c(1,2,1,4,6,7,8,2,3,4,8,1,2), v2=c(2,3,6,1,-3,-2,1,2,-3,6,7,-2,1))
groups  <- rle(dtf$v2 > 0)

dtf$groups<- rep(seq_along(groups$values), groups$lengths)
library(plyr)
daply(dtf, .(groups), function(x) sum(x$v1))[groups$values]
 1  3  5  7 
 8 10 12  2 

答案 1 :(得分:4)

这是一种方式:

t <- data.frame(v1=c(1,2,1,4,6,7,8,2,3,4,8,1,2), v2=c(2,3,6,1,-3,-2,1,2,-3,6,7,-2,1))

unname(with(t, tapply(v1[v2>0], cumsum(abs(diff(sign(c(0,v2)))))[v2>0], sum)))
[1]  8 10 12  2

起初看起来有点复杂:) cumsum(abs(diff(sign(c(0,v2)))))为每次正值或负值生成唯一的组ID。使用diffcumsum这是一个很常见的“常见”技巧......一个障碍是diff生成一个更短的向量 - 这就是为什么c(0, v2)使用。

答案 2 :(得分:3)

这是另一种方式。

> r <- rle(sign(t$v2))
> diff(c(0,cumsum(t$v1)[cumsum(r$lengths)]))[r$values==1]
[1]  8 10 12  2

如果将其拆分,则更容易理解;它的工作原理是挑选累积和的正确元素并减去它们。

> (s <- cumsum(t$v1))
 [1]  1  3  4  8 14 21 29 31 34 38 46 47 49
> (r <- rle(sign(t$v2)))
Run Length Encoding
  lengths: int [1:7] 4 2 2 1 2 1 1
  values : num [1:7] 1 -1 1 -1 1 -1 1
> (k <- cumsum(r$lengths))
[1]  4  6  8  9 11 12 13
> (a <- c(0,s[k]))
[    1]  0  8 21 31 34 46 47 49
> (d <- diff(a))
[1]  8 13 10  3 12  1  2
> d[r$values==1]
[1]  8 10 12  2

同样,但没有rle

> k <- which(diff(c(sign(t$v2),0))!=0)
> diff(c(0,cumsum(t$v1)[k]))[t$v2[k]>0]
[1]  8 10 12  2