简体   繁体   中英

How to use lapply function to instead of for loop in a custom function which is not vectorized in arguments

Firstly, let us generate data like this:

library(data.table)
data <- data.table(date = as.Date("2015-05-01")+0:299)
set.seed(123)
data[,":="(
   a = round(30*cumprod(1+rnorm(300,0.001,0.05)),2),
   b = rbinom(300,5000,0.8)
 )]

Then I want to use my custom function to operate multiple columns multiple times without manually typing out .Such as my custom function is add <- function(x,n) (x+n)

I provide my for loops code as following:

add <- function(x,n) (x+n)
n <- 3
freture_old <- c("a","b")
for(i in 1:n ){
  data[,(paste0(freture_old,"_",i)) := add(.SD,i),.SDcols =freture_old ]
}

Could you please tell me a lapply version to instead of for loop?

If all you want is to use an lapply loop instead of a for loop you really do not need to change much. For a data.table object it is even easier since every iteration will change the data.table without having to save a copy to the global environment. One thing I add just to suppress the output to the console is to wrap an invisible around it.

lapply(1:n,function(i) data[,paste0(freture_old,"_",i):=lapply(.SD,add,i),.SDcols =freture_old])

Note that if you assign this lapply to an object you will get a list of data.tables the size of the number of iterations or in this case 3. This will kill memory because you are really only interested in the final entry. Therefore just run the code without assigning it to a variable. Now if you do not assign it to anything you will get every iteration printed out to the console. So what I would suggest is to wrap an invisible around it like this:

invisible(lapply(1:n,function(i) data[,paste0(freture_old,"_",i):=lapply(.SD,add,i),.SDcols =freture_old]))

Hope this helps and let me know if you need me to add anything else to this answer. Good luck!

An option without R "loop" (quoted since ultimately its a loop at certain level somewhere):

data[,
    c(outer(freture_old, seq_len(n), paste, sep="_")) :=
        as.data.table(matrix(outer(as.matrix(.SD), seq_len(n), add), .N)),
    .SDcols=freture_old]

Or equivalently in base R:

setDF(data)
cbind(data, matrix(outer(as.matrix(data[, freture_old]), seq_len(n), add), 
    nrow(data)))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM