Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using match.call() with mapply

Tags:

r

mapply

I have a function that basically outputs a boolean condition as a string from the arguments (the details of the function don't matter here)

makeClause <-function(Sex=c("NA", "male", "female"),
        SmokingHx=c("NA", "current", "former", "never"),
        conjunction=c("&", "|")) {
    arglist = as.list(match.call())
    return(arglist)
}

I have a data frame that has all combinations of input arguments, as:

       Sex SmokingHx conjunction
1       NA        NA           &
2     Male        NA           &
...

Which I obtain this way:

combinations = expand.grid(Sex=c("NA", "male", "female"), 
                           SmokingHx=c("NA", "current", "former", "never"), 
                           conjunction=c("&", "|"),
                           stringsAsFactors=FALSE)

And I call makeClause with mapply:

mapply(makeClause, Sex=combinations$Sex,SmokingHx=combinations$SmokingHx, conjunction=combinations$conjunction)

Looking at the arglist variable I get:

$Sex
dots[[1L]][[1L]]

$SmokingHx
dots[[2L]][[1L]]

$conjunction
dots[[4L]][[1L]]

And if instead of as.list(match.call()) I call as.list(environment()) I get instead:

$Sex
[1] "male"

$SmokingHx
[1] "NA"

$conjunction
dots[[4L]][[1L]] # notice this is the only one for which I don't get the actual string

So I have two questions:

  1. Could you explain the R internals that lead to getting this as argument values instead of the actual string values ?
  2. How can I remedy this, i.e. get the string values in the argument list?

Thanks

like image 348
AdrienF Avatar asked Jun 03 '26 14:06

AdrienF


1 Answers

Why This is Happening:

match.call captures the quoted call as a language object. The dots business is what mapply is using to invoke your function, so the return value of match.call is correct. It is just matching the call that mapply constructed for your function and returning the quoted (i.e. unevaluated) values. Internally mapply is doing something like this (though not really since it is internal C code):

dots <- list(...)
call <- list()
for(j in seq_along(dots[[1]])) {
  for(i in seq_along(dots)) call[[i]] <- bquote(dots[[.(j)]][[.(i)]])
  eval(as.call(c(quote(FUN), call))))
}

If you look at as.call(c(FUN, call)) you would see something like FUN(dots[[1L]][[1L]], dots[[1L]][[2L]], dots[[1L]][[3L]]) which helps explain why you were getting the results you were getting.

How to Solve it:

You seem to want the values of your argument. You could evaluate what you get from match.call, or simpler, just use:

list(Sex, SmokingHx, conjunction)

If you want something that gets all the arguments of your function without having to know their names you can do something like:

mget(names(formals()))

Try (simplifying fun for clarity):

makeClause <-function(Sex, SmokingHx, conjunction) mget(names(formals()))

with(combinations, t(mapply(makeClause, Sex, SmokingHx, conjunction)))

Produces:

       Sex      SmokingHx conjunction
NA     "NA"     "NA"      "&"        
male   "male"   "NA"      "&"        
female "female" "NA"      "&"        
NA     "NA"     "current" "&"        
male   "male"   "current" "&"        
female "female" "current" "&"      
... further rows omitted
like image 91
BrodieG Avatar answered Jun 06 '26 05:06

BrodieG



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!