h.l.m
h.l.m

Reputation: 13465

assign new column for xts

I have made use of lapply to calculate cumulative products as a new column on a data set, BUT I had to get the data, calculate it, and then overwrite the original data using assign in each iteration of the lapply. I was wondering if there was a more elegant way of automatically assinging a new column name to an xts object

here is a mock example that produces the correct result...it should be copy paste-able into R

library(xts)
x <- xts(matrix(rnorm(10*1000,0.001,0.0001),ncol=10), Sys.Date()-c(1000:1))
colnames(x) <- paste0("x.",c(1:10))
tmp <- lapply(5:20, function(y){
    tmp.cum.prod <- rollapply(x,width=y,function(z){
        prod(rowMeans(z[,1:10])+1)-1
    },by.column=FALSE,align="right")
    orig.colnames <- colnames(x)
    x <- merge(x,tmp.cum.prod)
    colnames(x) <- c(orig.colnames,paste0("cum.prod.",y))
    assign("x",x,envir=.GlobalEnv)
})
tail(x)

But its the following lines that i think could probably be improved:

orig.colnames <- colnames(x)
x <- merge(x,tmp.cum.prod)
colnames(x) <- c(orig.colnames,paste0("cum.prod.",y))
assign("x",x,envir=.GlobalEnv)

Any suggestions? also if there are other lines that you think that could be improved in the above (e.g. the use of lapply), I am always keen to learn how to write more elegant code.

Thanks

Upvotes: 4

Views: 2218

Answers (2)

Joshua Ulrich
Joshua Ulrich

Reputation: 176648

If you're assigning to the global environment inside your lapply function, you should probably use a for loop instead. That's what I would do...

set.seed(21)
x <- xts(matrix(rnorm(10*1000,0.001,0.0001),ncol=10), Sys.Date()-1000:1)
colnames(x) <- paste0("x.",1:10)

rmx <- xts(rowMeans(x)+1,index(x))
for(i in 5:20) {
  tmp.cum.prod <- rollapplyr(rmx,i,prod,by.column=FALSE)-1
  colnames(tmp.cum.prod) <- paste0("cum.prod.",i)
  x <- merge(x,tmp.cum.prod)
}

Upvotes: 3

CHP
CHP

Reputation: 17189

You can use Reduce to do all the merge instead of looping.

> library(xts)
> x <- xts(matrix(rnorm(10*1000,0.001,0.0001),ncol=10), Sys.Date()-c(1000:1))
> colnames(x) <- paste0("x.",c(1:10))
> tmp <- lapply(5:20, function(y){
+   tmp.cum.prod <- rollapply(x,width=y,function(z){
+     prod(rowMeans(z[,1:10])+1)-1
+   },by.column=FALSE,align="right")
+   colnames(tmp.cum.prod) <- paste0("cum.prod.",y)
+   return(tmp.cum.prod)
+ })
> 
> result <- Reduce(function(...) merge(..., all=F), tmp, init = x)
> tail(result)
                    x.1          x.2          x.3          x.4          x.5          x.6          x.7          x.8          x.9         x.10
2013-02-20 0.0008919729 0.0010013599 0.0010276262 0.0007968856 0.0010731857 0.0010363689 0.0012281909 0.0010999609 0.0012081942 0.0010884836
2013-02-21 0.0009690167 0.0009131937 0.0009831485 0.0011843868 0.0011380318 0.0010424227 0.0011061298 0.0009944692 0.0010294051 0.0009762645
2013-02-22 0.0009269100 0.0010155799 0.0009445889 0.0010970406 0.0010646493 0.0011235968 0.0009402159 0.0010529831 0.0010884473 0.0008735272
2013-02-23 0.0009855041 0.0008282001 0.0011063870 0.0010430884 0.0008031531 0.0012577790 0.0009949316 0.0010046824 0.0011176581 0.0010516397
2013-02-24 0.0008176369 0.0009818399 0.0009964602 0.0009347190 0.0010362750 0.0010734247 0.0009749511 0.0010822521 0.0009335049 0.0010115921
2013-02-25 0.0009861176 0.0007606129 0.0010802525 0.0008771646 0.0010292476 0.0009319029 0.0011008009 0.0007901849 0.0011368412 0.0009677856
            cum.prod.5  cum.prod.6  cum.prod.7  cum.prod.8  cum.prod.9 cum.prod.10 cum.prod.11 cum.prod.12 cum.prod.13 cum.prod.14 cum.prod.15
2013-02-20 0.005080621 0.006084484 0.007080320 0.008074656 0.009105274  0.01009016  0.01111046  0.01212787  0.01317140  0.01416878  0.01516398
2013-02-21 0.005127238 0.006119520 0.007124420 0.008121286 0.009116649  0.01014833  0.01113423  0.01215559  0.01317405  0.01421867  0.01521707
2013-02-22 0.005119219 0.006145185 0.007138471 0.008144390 0.009142264  0.01013864  0.01117136  0.01215826  0.01318065  0.01420015  0.01524582
2013-02-23 0.005120808 0.006143740 0.007170751 0.008165050 0.009171994  0.01017089  0.01116827  0.01220205  0.01318996  0.01421339  0.01523392
2013-02-24 0.005105586 0.006110114 0.007134052 0.008162074 0.009157352  0.01016529  0.01116516  0.01216353  0.01319833  0.01418721  0.01521165
2013-02-25 0.005026133 0.006076609 0.007082108 0.008107036 0.009136051  0.01013229  0.01114120  0.01214204  0.01314137  0.01417717  0.01516701
           cum.prod.16 cum.prod.17 cum.prod.18 cum.prod.19 cum.prod.20
2013-02-20  0.01619964  0.01724359  0.01830398  0.01928576  0.02034408
2013-02-21  0.01621330  0.01725003  0.01829506  0.01935654  0.02033935
2013-02-22  0.01624524  0.01724248  0.01828025  0.01932634  0.02038890
2013-02-23  0.01628066  0.01728110  0.01827936  0.01931819  0.02036534
2013-02-24  0.01623318  0.01728095  0.01828237  0.01928161  0.02032147
2013-02-25  0.01619243  0.01721496  0.01826374  0.01926613  0.02026633

Upvotes: 2

Related Questions