-6

I have a zoo object in R of percent changes. I would like to compound those percent changes starting from 1 or 100 and see if we have compounded expansion/decay.

Lines <- "obs     date   pctchng comgrowth  
  1   2010-10-04 NA        100
  2   2010-10-01 .15       NA
  3   2010-09-30 .14       NA
  4   2010-09-29 -.05      NA
  5   2010-09-28 -.12      NA
  6   2010-09-27 .07       NA
  7   2010-09-24 -.15      NA
  8   2010-09-23 .186      NA
  9   2010-09-22 .01       NA
  10  2010-09-21 .03       NA
  11  2010-09-20 -.03      NA"
data <- read.zoo(textConnection(Lines), header=TRUE, index=2)
startobs <- 1
for (i in 1:100) {
  data[startobs+i,"comgrowth"] <- data[startobs+i-1,"comgrowth"] *
    (1+data[startobs+i,"pctchng"])
}

I am simplifying the data to make it simple to show but this is the idea I am trying to do. I realized the problem is when adding/subtracting/dividing/multiplying. For some reason I can say data[startobs+i,"comgrowth"]=data[startobs+i-1,"comgrowth"] but...

I cannot say data[startobs+i,"comgrowth"]=data[startobs+i-1,"comgrowth"]+data[startobs+i-2,"comgrowth"]. R won't let me add the +/-/* etc. and gives me this error

Error in NextMethod("[<-") : replacement has length zero

It's a syntatical problem, pure and simple. Does anyone know what I am doing wrong?

Joshua Ulrich
  • 173,410
  • 32
  • 338
  • 418
gabriel
  • 399
  • 2
  • 7
  • 17

2 Answers2

5

Even thought the object in your question cannot be a zoo object, I used it to create one... and to create a reproducible example.

library(zoo)
z <- structure(c(-0.03, 0.03, 0.01, 0.186, -0.15, 0.07, -0.12, -0.05, 
  0.14, 0.15, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 100),
  .Dim = c(11L, 2L), .Dimnames = list(NULL, c("pctchng", "comgrowth")),
  index = structure(c(14872, 14873, 14874, 14875, 14876, 14879, 14880,
  14881, 14882, 14883, 14886), class = "Date"), class = "zoo")
sobs <- 1
for (i in 1:10) {
  z[sobs+i,"comgrowth"]=z[sobs+i-1,"comgrowth"]*(1+z[sobs+i,"pctchng"])
}

The error is because Ops on zoo objects first aligns by index before performing the operation. Therefore, operations on zoo objects with no overlapping indices produces a zoo object with no observations, which could could have easily observed by running one iteration of your for loop.

i <- 1
sobs <- 1
z[sobs+i-1,"comgrowth"]*(1+z[sobs+i,"pctchng"])

The answer is to use vectorized functions and avoid the for loop all-together.

z <- structure(c(-0.03, 0.03, 0.01, 0.186, -0.15, 0.07, -0.12, -0.05,
  0.14, 0.15), .Dim = c(10L, 1L), .Dimnames = list(NULL, "pctchng"),
  index = structure(c(14872, 14873, 14874, 14875, 14876, 14879, 14880,
  14881, 14882, 14883), class = "Date"), class = "zoo")
z$comgrowth <- 100*cumprod(1+z$pctchng)
Community
  • 1
  • 1
Joshua Ulrich
  • 173,410
  • 32
  • 338
  • 418
  • z$comgrowth <- 100*cumprod(1+z$pctchng) doesn't get the get the "comgrowth" vector to start at a hundred. Believe me what I am trying to do cannot be vectorized. Is there any way to use the zoo package to do this operation observation-by-observation or is the only way to do make the dataset into a data.frame, running the loop there and then coercing it into a zoo package? – gabriel Jan 06 '13 at 22:34
  • 3
    @gabriel: I'm not going to spend more time on this until you spend the time to create a reproducible example. I edited your question so `data` is actually a zoo object, but the order is reversed because your initial object was in reverse-time order (which is impossible for a zoo object). – Joshua Ulrich Jan 06 '13 at 23:31
2

Besides the registration problem with Ops.zoo, there is an additional semantic problem with your data layout. Look at your data object after the read.zoo operation:

> data
           obs pctchng comgrowth
2010-09-20  11  -0.030        NA
2010-09-21  10   0.030        NA
2010-09-22   9   0.010        NA
2010-09-23   8   0.186        NA
2010-09-24   7  -0.150        NA
2010-09-27   6   0.070        NA
2010-09-28   5  -0.120        NA
2010-09-29   4  -0.050        NA
2010-09-30   3   0.140        NA
2010-10-01   2   0.150        NA
2010-10-04   1      NA       100

The date index reversed the order and the starting value of "comgrowth" entry is at the wrong end of the sequence.

IRTFM
  • 258,963
  • 21
  • 364
  • 487