4

In a by() function, I will use cor (correlation) to be the FUN there. However, I'd like to setup use="complete.obs" too.

I don't know how to pass this argument in the FUN = cor part.

For example,

by(data, INDICES=list(data$Age), FUN=cor)
Tomas
  • 57,621
  • 49
  • 238
  • 373
Leo5188
  • 1,967
  • 2
  • 17
  • 21

4 Answers4

7

probably

by(data, INDICES=list(data$Age), FUN=cor, use = "complete.obs")

will work.

the arguments to by are passed to FUN.

kohske
  • 65,572
  • 8
  • 165
  • 155
7

If you start looking around at various R help files for functions like by, you may start to notice a curious 'argument' popping up over and over again: .... You're going to see an ellipsis listed along with all the other arguments to a function.

This is actually an argument itself. It will collect any other arguments you pass and hand them off to subsequent functions called later. The documentation will usually tell you what function these arguments will be handed to.

In this case, in ?by we see this:

...  further arguments to FUN.

This means that any other arguments you pass to by that don't match the ones listed will be handed off to the function you pass to FUN.

Another common instance can be found in plot, where the documentation only lists two specific arguments, x and y. Then there's the ... which gathers up anything else you pass to plot and hands it off to methods or to par to set graphical parameter settings.

So in @kohske's example, use = "complete.obs" will be automatically passed on the cor, since it doesn't match any of the other arguments for by.

joran
  • 169,992
  • 32
  • 429
  • 468
2

@kohske and @joran give equivalent answers showing built in features of by (which are also present in apply and the entire plyr family) for passing additional arguments to the supplied function since this is a common application/problem. @Tomas also shows another way to specify an anonymous function which is just a function that calls the "real" function with certain parameters fixed. Fixing parameters to a function call (to effectively make a function with fewer arguments) is a common approach, especially in functional approaches to programming; in that context it is called currying or partial application.

library("functional")
by(data, INDICES=list(data$Age), FUN=Curry(cor, use = "complete.obs"))

This approach can be used when one function does not use ... to "pass along" arguments, and you want to indicate the only reason that an anonymous function is needed is to specify certain arguments.

Brian Diggs
  • 57,757
  • 13
  • 166
  • 188
  • interesting.... basically another way how to write the second possibility in my post. Or does it have some significant advantage over it? – Tomas Oct 13 '11 at 17:21
  • @TomasT. The advantages are syntactic and aesthetic. Using `Curry` indicates that all you are doing is specifying arguments. With a full anonymous function, you can do much more, but that requires more inspection to see what is actually being done. Additionally, with an anonymous function, you (may) need to specify all the other arguments if for no other reason to pass them along (although that could be done using `...`). – Brian Diggs Oct 13 '11 at 17:32
1

In general, you have 2 possibilities:

1) specify the arguments in the calling function (tapply() or by() in this case). This also works even if the key argument to fun() is not the first one:

fun <- function(arg1, arg2, arg3) { ... } # just to see how fun() looks like
tapply(var1, var2, fun, arg1 = something, arg3 = something2) 
    # arg2 will be filled by tapply

2) you may write your wrapper function (sometimes this is needed):

tapply(var1, var2, function (x) { fun(something, x, something2) })
Tomas
  • 57,621
  • 49
  • 238
  • 373