fred.schwartz
fred.schwartz

Reputation: 2155

R - can I write this loop as a apply function?

I've created the following loop but would like to write it as a lapply function. Is this possible? I'm trying to get my head around apply functions but haven't quite got the hang of it yet.

Decay <- function(x, decay=y) stats::filter(x, decay, method = "recursive")

d<-iris[,c("Sepal.Length","Sepal.Width","Petal.Length","Petal.Width")]

DecayX <- c(0.1,0.3,0.6,0.8,0.95)
DecVars = c("Sepal.Length","Petal.Width")

for (j in DecVars){
  for (i in DecayX){
    VarName <- paste(colnames(d[j]),i*100,"DEC",sep="_")
    d[[VarName]]<-Decay(d[j],i)
  }
}

Upvotes: 4

Views: 84

Answers (2)

clemens
clemens

Reputation: 6813

Another way would be to replace each for loop with an sapply() which is faster than for loops and doesn't require the use of expand.grid().

invisible(
  sapply(DecVars, function(j) {
    sapply(DecayX, function(i) {
      VarName <- paste(colnames(d[j]),i*100,"DEC",sep="_")
      d[[VarName]] <<- Decay(d[j],i)
    })
  })
)

You can see that this is a lot faster than using for loops and also marginally faster than the use of mapply() with grid.expand():

library(microbenchmark)

microbenchmark(
  'mapply' = {
    vars <- c(expand.grid(DecayX,DecVars,stringsAsFactors = F))
    invisible(
      mapply(function(x,DecV){VarName <- paste(colnames(d[DecV]),x*100,"DEC",sep="_");
      d[[VarName]]<<-Decay(d[DecV],x)},x=vars[[1]],DecV=vars[[2]])
    )},
  'sapply' = {
    invisible(
      sapply(DecVars, function(j) {
        sapply(DecayX, function(i) {
          VarName <- paste(colnames(d1[j]),i*100,"DEC",sep="_")
          d1[[VarName]] <<- Decay(d1[j],i)
        })
      })
    )
  },
  'for-loop' = {
    for (j in DecVars){
      for (i in DecayX){
        VarName <- paste(colnames(d[j]),i*100,"DEC",sep="_")
        d[[VarName]]<-Decay(d[j],i)
      }
    }
  },
  times = 1000)

Note: if you ignore the expand.grid() step, mapply() would be marginally faster.

Upvotes: 1

Andre Elrico
Andre Elrico

Reputation: 11480

I don't see any reason to use the apply family here.

You could use mapply

vars <- c(expand.grid(DecayX,DecVars,stringsAsFactors = F))
invisible(
mapply(function(x,DecV){VarName <- paste(colnames(d[DecV]),x*100,"DEC",sep="_");
                        d[[VarName]]<<-Decay(d[DecV],x)},x=vars[[1]],DecV=vars[[2]])
)

I think in cases of a double loop I would not use the apply family.

Upvotes: 4

Related Questions