Reputation: 13465
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
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
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