Hi Carl,
This is happening because of 'lazy evaluation'.
Arguments to a function are not evaluated until
they are needed. Thus the xlab and ylab deparsing
is not happening until you pass them off to the
plot() function. By this time you have altered
y inside your function.
If you comment out your line of code
'y<-y+(y==0)*1e-50' you'll see
the correct labels on your plot.
But with this line in play, you have a local
variable 'y' in your function's environment
so that is what substitute() evaluates.
Before this line, y is still a formal
argument, so that is what substitute will
evaluate.
When you add the dreck line of code,
you force lazy evaluation of the
ylab argument before you create an internal
y variable in the function's environment.
At that point y is still a formal argument
so in the lazy evaluation you pick up the
argument's name.
You can either put code such as these first two lines
to grab the names of x and y before you alter x and y
in your function
badplot <-
function(x, y, ylab, xlab, ...)
{
if (missing(ylab)) ylab <- deparse(substitute(y))
if (missing(xlab)) xlab <- deparse(substitute(x))
# un-comment either of the next two lines usually fixes the bug. why?
# cat(ylab,'\n')
# dreck<-ylab
# creating yy and using it instead of the input y fixes the bug. why?
#yy<-y
#yy<-yy+(yy==0)*1e-50
#y<-y+(y==0)*1e-50
#cat(xlab,ylab,'\n')
#plot(x,yy,xlab=xlab, ylab=ylab, ...)
plot(x,y,xlab=xlab, ylab=ylab, ...)
}
or use another mechanism such as match.call()
anotherbadplot <-
function(x, y, ylab=match.call()$y,
xlab=match.call()$x, ...)
{
# un-comment either of the next two lines usually fixes the bug. why?
# cat(ylab,'\n')
# dreck<-ylab
# creating yy and using it instead of the input y fixes the bug. why?
#yy<-y
#yy<-yy+(yy==0)*1e-50
y<-y+(y==0)*1e-50
#cat(xlab,ylab,'\n')
#plot(x,yy,xlab=xlab, ylab=ylab, ...)
plot(x,y,xlab=xlab, ylab=ylab, ...)
}
but I don't see any bug here.
HTH
Steve McKinney
-----Original Message-----
From: r-help-bounces at r-project.org on behalf of Carl Witthoft
Sent: Mon 6/9/2008 5:38 PM
To: r-help at r-project.org
Subject: [R] substitute() reading data instead of name
I seem to have run across a bug in which substitute() inside a function
definition gets 'confused.' The code is listed below.
The same behavior occurs under OSX 10.3.9, PPC, w/ R2.2 and Rgui 1.14
and under OSX 10.4.11 Intel w/ 2.70 and the latest Rgui.
What I see is that 'xlab' properly has the name of the data I entered
for the x-input. But 'ylab' contains the string ' c( {all the data
values in the y-input vector}) ' .
If I un-comment the 'cat(ylab)' line or the 'dreck<-y' line,
or if I
create yy<-y and use yy from there on out, everything works properly.
So, is this a bug, or am I a foolish n00b, or do I need to "flush"
something?
thanks for your help.
Carl
Here is the function .
********
# sample of odd behavior when using deparse(substitute()) in function
#call.
# I only see this w/ two or more such substitute() calls; use or don't
#use deparse(), no
# change in this behavior.
# If I do anything w/ ylab (cat it, or create dreck from it) then things
#seem to work
# If I pull the deparsing outside the function definition, it seems to
work -- but then of
# course the user can't specify his own y-label
#seems to be related to my conditional modification of y itself -- if
#comment out
# that line (y+(y==0)*1e-50) everything works. That y->yy seems to fix
#it as well.
#
badplot<-function(x, y, ylab=deparse(substitute(y)),
xlab=deparse(substitute(x)), ...)
{
# un-comment either of the next two lines usually fixes the bug. why?
# cat(ylab,'\n')
# dreck<-ylab
# creating yy and using it instead of the input y fixes the bug. why?
#yy<-y
#yy<-yy+(yy==0)*1e-50
y<-y+(y==0)*1e-50
#cat(xlab,ylab,'\n')
#plot(x,yy,xlab=xlab, ylab=ylab, ...)
plot(x,y,xlab=xlab, ylab=ylab, ...)
}
*******
As the comments say, doing just about any task that involves the input
variable 'y' cleans up the problem.
______________________________________________
R-help at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.