Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to reduce consecutive NAs to single NA

Tags:

r

I need to reduce the consecutive NA's in a vector to a single NA, without touching the other values.
So, for example, given a vector like this:

NA NA  8  7 NA NA NA NA NA  3  3 NA -1  4

what I need to get, is the following result:

NA  8  7 NA  3  3 NA -1  4

Currently, I'm using the following function:

reduceConsecutiveNA2One <- function(vect){
  enc <- rle(is.na(vect))

  # helper func
  tmpFun <- function(i){
    if(enc$values[i]){
      data.frame(L=c(enc$lengths[i]-1, 1), V=c(TRUE,FALSE))
    }else{
      data.frame(L=enc$lengths[i], V=enc$values[i])
    }
  }

  Df <- do.call(rbind.data.frame,lapply(1:length(enc$lengths),FUN=tmpFun))

  return(vect[rep.int(!Df$V,Df$L)])
}

and it seems to work fine, but probably there's a simpler/faster way to accomplish this task.

Any suggestions ?

Thanks in advance.

like image 383
digEmAll Avatar asked Sep 28 '12 15:09

digEmAll


2 Answers

Here's one idea:

x <- c(NA, NA,8,7,NA, NA, NA, NA, NA, 3, 3, NA, -1,  4)

x[!(is.na(x) & diff(c(FALSE, is.na(x)))==0)]
# [1] NA  8  7 NA  3  3 NA -1  4

## It also works for length-one vectors
x <- NA
x[!(is.na(x) & diff(c(FALSE, is.na(x)))==0)]
# [1] NA
like image 188
Josh O'Brien Avatar answered Oct 20 '22 20:10

Josh O'Brien


Maybe this could be useful

x <- c(NA, NA,8,7,NA, NA, NA, NA, NA, 3, 3, NA, -1,  4)
c(x[rowSums(is.na(embed(x,2)))!=2], x[length(x)])
[1] NA  8  7 NA  3  3 NA -1  4

If you want a function try:

myfun <- function(x){
  if(length(x)==1) {
    return(x)
  }
  else{
    return(c(x[rowSums(is.na(embed(x,2)))!=2], x[length(x)]))
  }
}

> myfun(x)
[1] NA  8  7 NA  3  3 NA -1  4
> y <- c(x, NA, NA, NA, 3)
> y
 [1] NA NA  8  7 NA NA NA NA NA  3  3 NA -1  4 NA NA NA  3
> myfun(y)
 [1] NA  8  7 NA  3  3 NA -1  4 NA  3
> myfun(NA)
[1] NA
> myfun(1)
[1] 1
like image 25
Jilber Urbina Avatar answered Oct 20 '22 20:10

Jilber Urbina