ManuelGoepferich / R-advanced

This is the R advanced course.
0 stars 0 forks source link

Function calls #4

Open ManuelGoepferich opened 8 years ago

ManuelGoepferich commented 8 years ago

R enables many ways to manipulate functions. A function in R has a body and formal arguments. Moreover, a function has an environment where it was created and an environment where it was called. match.fun can be used to find a function by its name.

f0 <- function(x = 5) x * 100
body(f0)                             ## the body of the function
formals(f0)                         ## the formal arguments
match.fun("f0")(10)            ## find a function by name

it is possible to create a function call and to evaluate this function call in a different environment. The function eval has the envir argument to define an environment where this expression should be evaluated.

f1 <- function(x) x + 5
calltof1 <- call("f1", 10) 
eval(calltof1)

With do.call one can supply the arguments of a function as a list. One idea would be to conduct functions with different arguments by updating the list of arguments.

f2 <- function(x,y) (x * y) + 5
arguments <- list(x = 5, y = 2)
do.call("f2", arguments)

What is the effect of invisible? In which situations could we use suppressWarnings?

f3 <- function(x,y){
      values <- rnorm(x, mean = y)
      out <- plot(hist(values))
      return(invisible(values))
}

f3(50, 5)

The definition of functions inside of other functions enables nameless or anonymous functions. In the next example the second function has no name.

f4 <- function(x, ...){
      y = 5 * x
        function(z, ...){ 
        return(z + y)
        }
}

f4(2)
f4(2)(5)

Handeling conditions (errors) is a main issue. The function try tests whether an expression (function call) can be conducted successfully. If there is no error the value will be returned. If an error occurred the output object will be of the class "try-error".

f5 <- function(x){
      condition  <- try(log(x))
      if(class(condition) == "try-error" ){
      stop("Error with the log function")  
      } else {
      return(condition)  
      }
}

f5("A")  ## This will give two errors. Which makes more sense?
f5(10)

Task: Write a function named recursive. This functions takes as input a function f and a value x. f should be applied two times to x. In other words: recursive (log, 100) == log(log(100))

In object oriented programming a developer defines objects (S3 or S4) that will have class names (like ExpressionSet). Generic functions apply different methods in dependance of the input object and will return objects of a desired class. An example: If you want to plot a matrix or a vector you call (the generic) plot function. This function calls now the right method for a matrix or a vector.

plot(c(1:4))
mat1 <- matrix(rnorm(24), ncol = 4)
plot(mat1)

Here is a definition of a generic function named label_it:

setGeneric(name = "label_it",
           def  = function(object,
                           label){  
             standardGeneric("label_it")
           }
          )

setMethod(f = "label_it",
          signature = c("vector"),
          definition = function(object,
                                label){  
          names(object) <- label  
          return(object)
          })

setMethod(f = "label_it",
          signature = c("matrix"),
          definition = function(object,
                                label){  
          colnames(object) <- label  
          return(object)  
          })

This function can now process two classes of input objects.

label_it(c(1:4), label = c("A", "B", "C", "D"))

label_it(mat1, label = c("A", "B", "C", "D"))
ManuelGoepferich commented 8 years ago