Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R: Transforming a vector into a list of arguments

Tags:

r

I would like to apply a function to a vector. However, the function is expecting a sequence of arguments. Thus, I need to "split" the vector into unrelated arguments.

Suppose that I have a dataframe called dta. I want to run a function, say mean on one of its column, say DV.

The following shows the problem

call("mean", dta$DV)

returns

mean(c(0.371, -0.860, etc... ))

The fact that the column is a vector is not compatible with the function mean which expects a sequence of arguments, not combined.

The solution should work if "mean" is replaced by a variable containing a string, e.g.

fun <- "mean"

call( fun, dta$DV)
like image 778
Denis Cousineau Avatar asked Oct 19 '25 21:10

Denis Cousineau


1 Answers

R has functions that are not completely consistent. For instance, min and max accept arbitrary numbers of arguments, where all unrecognized arguments are considered in the mathematical calculation. mean is not, it must have all numbers to be considered as the first (or named x=) argument.

min(1,20,0)
# [1] 0
min(c(1,20,0))
# [1] 0
mean(1,20,0) # might not be what one would expect
# [1] 1
mean(c(1,20,0))
# [1] 7

For the curious, the 20 and 0 are not ignored, the first mean call is interpreted as mean(0, trim=20, na.rm=0) (where na.rm=0 is effectively the same as na.rm=FALSE).

Your use of call is a little off. From the help ?call,

call returns an unevaluated function call

which doesn't really help you a lot. You might do eval(call(...)), but that seems silly in light of this next function.

Use of do.call is a bit more straight forward. I can take as its first argument: a function (anonymous or named) or a character string which matches a function. There are actually speed differences between using one or the other, so I tend to use a character reference to the function name when able. (I don't recall the reference that quantifies this assertion, I'll include it if I find it soon.)

For functions like min above that can accept any number of arguments, one can do this:

args <- c(1,20,0)

as.list(args)
# [[1]]
# [1] 1
# [[2]]
# [1] 20
# [[3]]
# [1] 0
do.call("min", as.list(args)) # == min(1,20,0)
# [1] 0

list(args)
# [[1]]
# [1]  1 20  0
do.call("min", list(args)) # == min(c(1,20,0))
# [1] 0

However, for mean and similar, you need to force the latter behavior:

do.call("mean", list(args)) # == mean(c(1,20,0))
# [1] 7

For you to call a function with programmatically-defined arguments, you need to use do.call.

like image 67
r2evans Avatar answered Oct 22 '25 13:10

r2evans