[R] Puzzled over curve() syntax.
Duncan Murdoch
murdoch at stats.uwo.ca
Thu Oct 27 16:29:38 CEST 2005
On 10/27/2005 9:50 AM, Rolf Turner wrote:
> It's probably toadally elementary (and, like, duhhhhh) but
> I can't figure out why the following doesn't work:
>
> curve(function(x){qnorm(x,4,25)},from=0,to=1)
>
> I get the error:
>
> Error in xy.coords(x, y, xlabel, ylabel, log) :
> 'x' and 'y' lengths differ
>
> But if I do
>
> foo <- function(x){qnorm(x,4,25)}
> curve(foo,from=0,to=1)
>
> it goes like a train.
>
> Also
>
> plot(function(x){qnorm(x,4,25)},from=0,to=1)
>
> works just fine.
>
> I'm using
>
> > version
> _
> platform sparc-sun-solaris2.9
> arch sparc
> os solaris2.9
> system sparc, solaris2.9
> status
> major 2
> minor 2.0
> year 2005
> month 10
> day 06
> svn rev 35749
> language R
>
> This is just idle curiousity I guess, but I would like to deepen my
> understanding. There's probably something about the ``expression''
> concept that I'm not grokking here ....
It's the way curve is written (and documented, though perhaps a little
obscurely). If you debug it, you'll see that eventually your function
gets assigned to a variable called "expr", and a nice list of values
gets assigned to "x", then it tries to evaluate
y <- eval(expr, envir = list(x = x), enclos = parent.frame())
But if you evaluate expr, you just get the function back, you don't call
it. The problem is that curve was written assuming you'd call it as
curve(qnorm(x,4,25),from=0,to=1)
in which case the expression "qnorm(x,4,25)" gets evaluated at those x
values and things are fine.
I don't think this is a bug, but it might be worth fixing so your code
works too. It's a little tricky, because to know that you passed a
function in, you probably want to evaluate it; but if you evaluate
"qnorm(x,4,25)" before you've set up x, you'll get an error.
A fix is to add an additional else clause after the first test, namely
else if (is.language(sexpr) && identical(sexpr[[1]],
as.name("function"))) {
expr <- substitute(do.call(expr, list(x)), list(expr=expr))
if (is.null(ylab))
ylab <- deparse(sexpr)
}
but this still doesn't handle the case where you've given a more general
expression that returns a function, e.g. picking one out of a list.
You'll probably need another argument to distinguish the case of an
expression returning y values from an expression returning a function,
and I'm not sure that level of elaboration would really be a good idea.
Duncan Murdoch
More information about the R-help
mailing list