How to Use Functions as Arguments in R - dummies

How to Use Functions as Arguments in R

By Andrie de Vries, Joris Meys

In R, you can pass a function itself as an argument. You can easily assign the complete code of a function to a new object. Similarly, you also can assign the function code to an argument. This opens up a complete new world of possibilities. Here are a few examples.

Different ways to round in R

There are different options for rounding numbers. The addPercent() function uses round() for that, but you may want to use one of the other options — for example, signif(). The signif() function doesn’t round to a specific number of decimals; instead, it rounds to a specific number of digits. You can’t use it before you call addPercent(), because the round() function in that body will mess everything up again.

Of course, you could write a second function specifically for that, but there’s no need to do so. Instead, you can just adapt addPercent() in such a way that you simply give the function you want to use as an argument, like this:

addPercent <- function(x, mult = 100, FUN = round, ...){
 percent <- FUN(x * mult, ...)
 paste(percent, "%", sep = ")

You add an argument to the list — in this case, FUN — and then you can use the name of that argument as a function. Also, specifying a default value works exactly the same as with other arguments; just specify the default value — in this case, round — after an = sign.

If you want to use signif() now for rounding the numbers to three digits, you can easily do that using the following call to addPercent():

> addPercent(new.numbers, FUN = signif, digits = 3)
[1] "82.2%" "2.49%" "162%" "40%"

What happens here?

  1. As before, R takes the vector new.numbers and multiplies it by 100, because that’s the default value for mult.

  2. R assigns the function code of signif to FUN, so now FUN() is a perfect copy of signif() and works exactly the same way.

  3. R takes the argument digits and passes it on to FUN().

Note the absence of parentheses in the argument assignment. If you added the parentheses there, you would assign the result of a call to signif() instead of the function itself. R would interpret signif(), in that case, as a nested function, and that’s not what you want. Plus, R would throw an error because, in that case, you call signif() without arguments, and R doesn’t like that.

Use anonymous functions

You can, of course, use any function you want for the FUN argument. That function doesn’t even need to have a name, because you effectively copy the code. So, instead of giving a function name, you can just add the code as an argument as an anonymous function. An anonymous function is a function without a name.

Suppose you have the quarterly profits of your company in a vector like this:

> profits <- c(2100, 1430, 3580, 5230)

Your boss asks you to report how much profit was made in each quarter relative to the total for the year, and, of course, you want to use your new addPercent() function. To calculate the relative profits in percent, you could write a rel.profit() function like this:

> rel.profit <- function(x) round(x / sum(x) * 100)

But you don’t have to. Instead, you can just use the function body itself as an argument, as in the following example:

> addPercent(profits,
        FUN = function(x) round(x / sum(x) * 100) )
[1] "17%" "12%" "29%" "42%"

Of course, this isn’t the optimal way of doing this specific task. You could easily have gotten the same result with the following code:

> addPercent(profits / sum(profits))
[1] "17%" "12%" "29%" "42%"