Maxim.K
Maxim.K

Reputation: 4180

R: passing argument name in dots (...) through a third string variable

Imagine you have a simple function that specifies which statistical tests to run for each variable. Its syntax, simplified for the purposes of this question is as follows:

test <- function(...) {
  x <- list(...)
  return(x)
} 

which takes argument pairs such as Gender = 'Tukey', and intends to pass its result to other functions down the line. The output of test() is as follows:

test(Gender = 'Tukey')
# $Gender
# [1] "Tukey"

What is desired is the ability to replace the literal Gender by a dynamically assigned variable varname (e.g., for looping purposes). Currently what happens is:

varname <- 'Gender'
test(varname = 'Tukey')
# $varname
# [1] "Tukey"

but what is desired is this:

varname <- 'Gender'
test(varname = 'Tukey')
# $Gender
# [1] "Tukey"

I tried tinkering with functions such as eval() and parse(), but to no avail. In practice, I resolved the issue by simply renaming the resulting list, but it is an ugly solution and I am sure there is an elegant R way to achieve it. Thank in advance for the educational value of your answer.

NB: This question occurred to me while trying to program a custom function which uses mcp() from the effects package in its internals. The said mcp() function is the real world counterpart of test().

EDIT1: Perhaps it needs to be clarified that (for educational purposes) changing test() is not an option. The question is about how to pass the tricky argument to test(). If you take a look at NB, it becomes clear why: the real world counterpart of test(), namely mcp(), comes with a package. And while it is possible to create a modified copy of it, I am really curious whether there exists a simple solution in somehow 'converting' the dynamically assigned variable to a literal in the context of dot-arguments.

Upvotes: 1

Views: 231

Answers (3)

alan ocallaghan
alan ocallaghan

Reputation: 3038

What about this:

varname <- "Gender"
args <- list()
args[[varname]] <- "Tukey"
do.call(test, args)

Upvotes: 1

akrun
akrun

Reputation: 887088

We can use

test <- function(...) {
  x <- list(...)
  if(exists(names(x))) names(x) <- get(names(x))
  x

} 



test(Gender = 'Tukey')
#$Gender
#[1] "Tukey"

test(varname = 'Tukey')
#$Gender
#[1] "Tukey"

Upvotes: 2

Jordi
Jordi

Reputation: 1343

This works:

test <- function(...) {
  x = list(...)
  names(x) <- sapply(names(x), 
                     function(p) eval(as.symbol(p)))
  return(x)
}

apple = "orange"
test(apple = 5)

Upvotes: 2

Related Questions