Produnis
Produnis

Reputation: 567

Passing arguments to iterated function through apply

I have a function like this dummy-one:

FUN <- function(x, parameter){
  if (parameter == 1){
      z <- DO SOMETHING WITH "x"}
  if (parameter ==2){
      z <- DO OTHER STUFF WITH "x"}
return(z)
}

Now, I would like to use the function on a dataset using apply. The problem is, that apply(data,1,FUN(parameter=1))

wont work, as FUN doesn't know what "x" is. Is there a way to tell apply to call FUN with "x" as the current row/col? `

Upvotes: 35

Views: 30340

Answers (3)

Rob
Rob

Reputation: 874

Here's a practical example of passing arguments using the ... object and *apply. It's slick, and this seemed like an easy example to explain the use. An important point to remember is when you define an argument as ... all calls to that function must have named arguments. (so R understands what you're trying to put where). For example, I could have called times <- fperform(longfunction, 10, noise = 5000) but leaving off noise = would have given me an error because it's being passed through ... My personal style is to name all of the arguments if a ... is used just to be safe.

You can see that the argument noise is being defined in the call to fperform(FUN = longfunction, ntimes = 10, noise = 5000) but isn't being used for another 2 levels with the call to diff <- rbind(c(x, runtime(FUN, ...))) and ultimately fun <- FUN(...)

# Made this to take up time
longfunction <- function(noise = 2500, ...) {
  lapply(seq(noise), function(x) {
    z <- noise * runif(x)
  })
}

# Takes a function and clocks the runtime
runtime <- function(FUN, display = TRUE, ...) {
  before <- Sys.time()
  fun <- FUN(...)
  after <- Sys.time()
  if (isTRUE(display)) {
    print(after-before)
  }
  else {
    after-before
  }
}

# Vectorizes runtime() to allow for multiple tests
fperform <- function(FUN, ntimes = 10, ...) {   
  out <- sapply(seq(ntimes), function(x) {
    diff <- rbind(c(x, runtime(FUN, ...)))
  })
}

times <- fperform(FUN = longfunction, ntimes = 10, noise = 5000)

avgtime <- mean(times[2,])
print(paste("Average Time difference of ", avgtime, " secs", sep=""))

Upvotes: 3

Chase
Chase

Reputation: 69151

You can make an anonymous function within the call to apply so that FUN will know what "x" is:

apply(data, 1, function(x) FUN(x, parameter = 1))

See ?apply for examples at the bottom that use this method.

Upvotes: 17

Joshua Ulrich
Joshua Ulrich

Reputation: 176648

You want apply(data,1,FUN,parameter=1). Note the ... in the function definition:

> args(apply)
function (X, MARGIN, FUN, ...) 
NULL

and the corresponding entry in the documentation:

...: optional arguments to ‘FUN’.

Upvotes: 37

Related Questions