Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manage parameters and arguments in R?

Tags:

r

This is a pretty simple and general question, but I haven't seen it already discussed. I hope I haven't missed anything.

I am starting to design big programs with several layers of functions, and while there is clear strategies in other programming languages, I can't find a canonical solution in R on how to treat "parameters" of a function that will also have "arguments". I make a conceptual difference between "parameters" and "arguments", even if they are actually the same to the function: inputs. The former will be set on higher level, and not change often, while the latter is the real data that the function will process.

Let consider this simple example: simple schema

The subfunction of interest SF() is queried many times with different arguments by the "WORKER", but with the same parameters, that are set "above". Of course the same question applies to more complicated cases with several layers.

I see two ways of dealing with that: 1. Passing down everything, but : a. You'll end up with a myriad of arguments in your function call, or a structure enclosing all these arguments. b. Because R makes copies of arguments to call functions, it may not be very efficient. 2. Dynamically evaluating the functions each time you change the parameters, and "hardwire" them into the function definition. But I am not sure how to do that, especially in a clean way.

None of this seems really likable, so I was wondering if you guys had an opinion on that matter? Maybe we could use some environmental features of R? :-)

Thanks!

EDIT: Because for some, code is better than graphs, here is a dummy example in which I used the method "1.", passing all the arguments over. If I have many layers and subfunctions, passing all the parameters to the intermediate layers (here, WORKER()) seems not great. (from a code and a performance perspective)

F <- function(){
  param <- getParam()
  result <- WORKER(param)
  return(result)
}

getParam <- function(){
  return('O')
}

WORKER <- function(param) {
  X <- LETTERS[1:20]
  interm.result <- sapply(X,SF,param) # The use of sapply here negates maybe the performance issue?
  return(which(interm.result=='SO'))
}

SF <- function(x,param) {
  paste0(x,param)
}

EDIT 2 : The simplicity of the example above mislead some of the kind people looking at my problem, so here is a more concrete illustration, using a discrete gradient descent. Again, I kept it simple, so everything could be written in the same big function, but that's not what I want to do for my real problem.

gradientDescent <- function(initialPoint= 0.5, type = 'sin', iter_max = 100){ 
  point <- initialPoint
  iter <- 1
  E <- 3
  deltaError <- 1
  eprev <- 0
  while (abs(deltaError) > 10^(-2) | iter < iter_max) {
    v_points <- point + -100:100 / 1000
    E <- sapply(v_points, computeError, type)
    point <- v_points[which.min(E)]
    ef <- min(E)
    deltaError <- ef - eprev
    eprev <- ef
    iter <- iter+1
  }
  print(point)
  return(point)
}

computeError <- function(point, type) {
  if (type == 'sin') {
    e <- sin(point)
  } else if (type == 'cos') {
    e <- cos(point)    
  }
}

I find it non-optimal to pass the "type" parameter of the subfunction each time it is evaluated. It seem that the reference brought by @hadley to Closures and explanation of @Greg are good tracks to the solution I need.

like image 882
Antoine Lizée Avatar asked Aug 30 '13 22:08

Antoine Lizée


People also ask

How do you use parameters in R?

Parameters in an R Markdown document are very simple to use. In the yaml header (the section at the top of the markdown document), you just have to add a couple new lines for your parameters to hardcode them in. Once they're coded in, they will be available in the params object for use in the rest of the analysis.

What does parameter mean in R?

From what I read and understood so far, a parameter is what a function can take as input. For example if I have a function that calculates the sum of two values, sum(value1, value2) , 'value1' and 'value2' are the function's parameters. If we are calling a function, we call the values passed to the function arguments.

How many arguments can a function have in R?

Having said that, the average R function does use about 4 arguments, so if you keep your functions to around 4 arguments you'll be approaching the sort of consensus of a large number of R developers.


2 Answers

I think you may be looking for lexical scoping. R uses lexical scoping which means that if you define the functions WORKER and SF inside of F, then they will be able to access the current value of param without it being passed down.

If you cannot take advantage of lexical scoping (SF must be defined outside of F), then another option is to create a new environment to store your parameters in, then if all the needed functions have access to this environment (either by passing explicitly, or by inheritance (making this environment the enclosing environment of the functions)) then F can assign param into this environment and the other functions can access the value.

like image 108
Greg Snow Avatar answered Oct 20 '22 19:10

Greg Snow


At the risk of speaking for others, I think the reason your question is getting both interest and a dearth of answers is that you seem to be making this overcomplicated.

Certainly given the task shown in your example, I'd do something more like this:

SF <- function(x, par) {
    paste0(x, par)
}

F <- function(param) {
    which(sapply(LETTERS[1:20], FUN = SF, par = param) == "SO")
}

F(param="O")
#  S 
# 19 

Or, using the lexical scoping that Greg Snow referred to:

F <- function(param) {
    SF <- function(x) {
         paste0(x, param)
    }
    which(sapply(LETTERS[1:20], FUN = SF) == "SO")
}
F(param="O")

Or, in reality and taking advantage of the fact that paste0() is vectorized:

F <- function(param) {
    which(paste0(LETTERS[1:20], param) == "SO")
}
F("O")
# [1] 19

I understand my answer may appear overly simplistic: you clearly have something more complicated in mind, but I think you need to better show us what that is. To get more help I suggest you follow the suggestions in @baptiste's second comment, giving us a less abstract example and explaining why you call F() and getParam() without any arguments (and also perhaps demonstrating why you need a getParam() function at all).

like image 29
Josh O'Brien Avatar answered Oct 20 '22 20:10

Josh O'Brien