[R] Filling NA with cumprod?

Petr Savicky savicky at cs.cas.cz
Fri May 25 08:24:07 CEST 2012


On Thu, May 24, 2012 at 08:24:38PM -0700, igorre25 wrote:
> Hello,
> 
> I need to build certain interpolation logic using R.  Unfortunately, I just
> started using R, and I'm not familiar with lots of advanced or just
> convenient features of the language to make this simpler.  So I struggled
> for few days and pretty much reduced the whole exercise  to the following
> problem, which I cannot resolve:
> 
> Assume we have a vector of some values with NA:
> a <- c(1, 2, 3, NA, NA, 6, 7, NA, NA, 10)
> 
> and some coefficients as a vector of the same length:
> 
> f <- c(0.9, 1.1, 0.9, 1.1, 0.9, 1.1, 0.9, 1.1, 0.9, 1.1)
> 
> I need to come up with function to get the following output
> 
> o[1] = a[1]
> o[2] = a[2]
> o[3] = a[3]
> o[4] = o[3]*[f3] # Because a[3] is NA
> o[5] = o[4]*[f4] # Because a[4] is NA; This looks like recursive
> calculations;  If the rest of the elements we NA, I would use a * c(rep(1,
> 3), cumprod(f[3:9])), but that's not the case
> o[6] = a[6] # Not NA anymore
> o[7] = a[7]
> o[8] = o[7]*f[7] # Again a[8] is NA
> o[9] = o[8]*f[8]
> o[10] = a[10] # Not NA
> 
> Even though my explanation may seems complex, in reality the requirement is
> pretty simple and in Excel is achieved with a very short formula.
> 
> The need to use R is to demonstrate capabilities of the language and then to
> expand to more complex problems.

Hello:

How is the output defined, if a[1] is NA?

I think, you are not asking for a loop solution. However, in this case,
it can be a reasonable option. For example

  a <- c(1, 2, 3, NA, NA, 6, 7, NA, NA, 10)
  f <- c(0.9, 1.1, 0.9, 1.1, 0.9, 1.1, 0.9, 1.1, 0.9, 1.1)
  n <- length(a)
  o <- rep(NA, times=n)
 
  prev <- 1
  for (i in 1:n) {
      if (is.na(a[i])) {
          o[i] <- f[i]*prev
      } else {
          o[i] <- a[i]
      }
      prev <- o[i]
  }

A more straightforward translation of the Excel formulas is

  getCell <- function(i)
  {
      if (i == 0) return(1)
      if (is.na(a[i])) {
          return(f[i]*getCell(i-1))
      } else {
          return(a[i])
      }
  }

  x <- rep(NA, times=n)
  for (i in 1:n) {
      x[i] <- getCell(i)
  }

  identical(o, x) # [1] TRUE

Petr Savicky.



More information about the R-help mailing list