[R] Problem with do.call().

Duncan Murdoch murdoch.duncan at gmail.com
Fri Mar 28 00:49:06 CET 2014


On 27/03/2014, 7:17 PM, Rolf Turner wrote:
>
>
> I was under the impression that
>
> 	do.call(foo,list(x=x,y=y))
>
> should yield the same result as
>
> 	foo(x,y).
>
> However if I do
>
> 	x <- 1:10
> 	y <- (x-5.5)^2
> 	do.call(plot)
>
> I get the expected plot but with the y-values (surrounded by c()) being
> printed (vertically) in the left-hand margin of the plot.
>
> The help for do.call() says:
>
>> The behavior of some functions, such as substitute, will not be the
>> same for functions evaluated using do.call as if they were evaluated
>> from the interpreter. The precise semantics are currently undefined and
>> subject to change.
>
> Am I being bitten by an instance of this phenomenon?  Seems strange.
>
> I would be grateful for enlightenment.

Yes, you are being bitten that way.

Here are some details.  Enlightenment?  Probably not...

When you call a function as plot(x,y), R constructs "promises" for the 
arguments:  these are objects that contain the expressions x and y, 
associated with the first two arguments to plot (which happen to be 
named x and y as well).  When the plot function makes use of its 
arguments the first time, the promises are evaluated, which means that 
the expressions are evaluated and the values are stored in the promises. 
  Later evaluations just retrieve that stored value.

When plot() builds its labels, it uses substitute() on the argument. 
When substitute is given a promise, it returns the expression associated 
with it, which plot converts to a string: so the labels on plot(x, y) 
end up as "x" and "y".

That's the normal way things happen.

When you call do.call() instead, it evaluates its "args" argument, which 
is list(x=x,y=y) in your example.  That gives it a named list with names 
"x" and "y".  The values in those slots are the evaluated values of x 
and y.  It passes these to plot(), associating those values with the 
arguments named x and y.  It doesn't ever construct promises like in the 
usual mechanism, so substitute() can't find an expression to convert 
into a label.  It just gives the value, which plot converts to a string.

So there you are.  Feel enlightened?

Here's the most useful part of the post:  to get what you want, use

do.call(plot, list(x=x, y=y, xlab="x", ylab="y"))

Duncan Murdoch




More information about the R-help mailing list