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
partial cumsum
2 messages · Carl Witthoft, Marc Schwartz
On Nov 11, 2009, at 4:45 PM, Carl Witthoft wrote:
> By Bill Dunlap:
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
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