tags:

views:

148

answers:

2

I'm learning R and I'm curious... I need a function that does this:

> fillInTheBlanks(c(1, NA, NA, 2, 3, NA, 4))
[1] 1 1 1 2 3 3 4
> fillInTheBlanks(c(1, 2, 3, 4))
[1] 1 2 3 4

and I produced this one... but I suspect there's a more R way to do this.

fillInTheBlanks <- function(v) {
  ## replace each NA with the latest preceding available value

  orig <- v
  result <- v
  for(i in 1:length(v)) {
    value <- v[i]
    if (!is.na(value))
      result[i:length(v)] <- value
  }
  return(result)
}
+4  A: 

Package zoo has a function na.locf():

R> library("zoo")
R> na.locf(c(1, 2, 3, 4))
[1] 1 2 3 4
R> na.locf(c(1, NA, NA, 2, 3, NA, 4))
[1] 1 1 1 2 3 3 4

na.locf: Last Observation Carried Forward; Generic function for replacing each ‘NA’ with the most recent non-‘NA’ prior to it.

See the source code of the function na.locf.default, it doesn't need a for-loop.

rcs
and its fromLast parameter solves the symmetric question! (I'm reading the code of na.locf.R now and it is full of things worth reading)
mariotomo
interesting source. I'm adding an other answer, distilled from yours and from the zoo library.
mariotomo
+3  A: 

I'm doing some minimal copy&paste from the zoo library (thanks again rcs for pointing me at it) and this is what I really needed:

fillInTheBlanks <- function(S) {
  ## NA in S are replaced with observed values

  ## accepts a vector possibly holding NA values and returns a vector
  ## where all observed values are carried forward and the first is
  ## also carried backward.  cfr na.locf from zoo library.
  L <- !is.na(S)
  c(S[L][1], S[L])[cumsum(L)+1]
}
mariotomo
Whoah. Cryptic but nice.
Thrawn