Skip to content

partial cumsum

2 messages · Carl Witthoft, Marc Schwartz

#
quote:
    > x <- c(1, 2, 3, NA, 5, 6, 7, 8, 9, 10)
    > rev(cumsum(rev(is.na(x))))
     [1] 1 1 1 1 0 0 0 0 0 0
A more natural way to do this is
    > cumsum(is.na(c(NA,x[-length(x)])))
     [1] 1 1 1 1 2 2 2 2 2 2
endquote

Both of which suggest the original problem could also be dealt with by 
using rle().  Something like

xna<-is.na(x)
rle(xna)
and then apply cumsum to sections of x based onthe lengths returned by rle

Carl
#
On Nov 11, 2009, at 4:45 PM, Carl Witthoft wrote:
> By Bill Dunlap:
Which would be something along the lines of the following:

rle.x <- rle(!is.na(x))$lengths

 > rle.x
[1] 3 1 6

 > as.numeric(unlist(sapply(split(x, rep(seq(along = rle.x), rle.x)),  
cumsum)))
  [1]  1  3  6 NA  5 11 18 26 35 45


Which is what I had been working on until I saw Bill's more elegant  
"one-liner" solution...  :-)

The interim use of split() gets you 'x' split by where the NA's occur:

 > rep(seq(along = rle.x), rle.x)
  [1] 1 1 1 2 3 3 3 3 3 3

 > split(x, rep(seq(along = rle.x), rle.x))
$`1`
[1] 1 2 3

$`2`
[1] NA

$`3`
[1]  5  6  7  8  9 10

and then you use cumsum() in sapply() (or lapply()) on each list  
element and coerce the result back to an un-named numeric vector.

Regards,

Marc Schwartz