[R] A strange behaviour in the graphical function "curve"

Berend Hasselman bhh at xs4all.nl
Fri Apr 12 07:37:15 CEST 2013


On 12-04-2013, at 05:15, Julio Sergio <juliosergio at gmail.com> wrote:

> I thought the curve function was a very flexible way to draw functions. So I 
> could plot funtions like the following:
> 
>   # I created a function to produce functions, for instance:
>   fp <- function(m,b) function(x) sin(x) + m*x + b
>   # So I can produce a function like this
>   ff <- fp(-0.08, 0.2)
>   ff(1.5)
>   # Is the same as executing
>   sin(1.5) - 0.08*1.5 + 0.2
>   # Let's plot this
>   plot(fp(0.1,0.1),xlim=c(-2*pi,2*pi),col="red")
>   curve(fp(0,0)(x),add=T)
>   curve(ff(x),add=T,col="blue")
> 
> When I get to plot some more complex functions, "curve", instead of taking 
> the argument function as a black-box, i.e., something that takes an argument 
> (the x) and returns a value (the y), seems to inspect the inner code of the 
> argument function in a way that even R itself doesn't do. See what I'm 
> talking about:
> 
>   # A function that returns a 2-element vector, given a
>   # single argument
>   zetas <- function(alpha) {z <- qnorm(alpha/2); c(z,-z)}
> 
>   # A transformation function - it can take a vector as
>   # its z argument
>   Tzx <- function(z, sigma_p, mu_p) sigma_p*z + mu_p
> 
>   # Another transformation function similar to the
>   # previous one - it can take a vector as its x argument
>   Txz <- function(x, sigma_p, mu_p) (x - mu_p)/sigma_p
> 
>   # The general function with several arguments
>   BetaG <- function(mu, alpha, n, sigma, mu_0) {
>     lasZ <- zetas(alpha) # It is a vector
>     sigma_M <- sigma/sqrt(n)
>     lasX <- Tzx(lasZ, sigma_M, mu_0) # Another vector(transf. from lasZ)
>     NewZ <- Txz(lasX, sigma_M, mu) # A new vector:transf. from lasX
>     # And the result is a single value:
>     pnorm(NewZ[2]) - pnorm(NewZ[1])
>   }
> 
>   # Now, let's have a function of a single argument, giving
>   # particular values to all other arguments; so miBeta depends
>   # only on the value of the argument 'mu'
>   miBeta <- function(mu) BetaG(mu, 0.05, 36, 48, 400)
> 
>   # I can call this function with 420 and it works
>   miBeta(420)
> 
>   # But when the time comes to plot the function, it doesn't work
>   curve(miBeta,xlim=c(370,430), xlab="mu", ylab="L(mu)")
> 
> 
> When I called miBeta with any value the R interpreter didn't complain. 
> However, "curve" seems to go deeper than the R interpreter and issues 
> several error messages:
> 
> Error en curve(miBeta, xlim = c(370, 430), xlab = "mu", ylab = "L(mu)") : 
>  'expr' did not evaluate to an object of length 'n'
>  Además: Mensajes de aviso perdidos
>  In x - mu_p :
>    longitud de objeto mayor no es múltiplo de la longitud de uno menor
> 
> Do you have any idea on why "curve" behaves this way?

Yes. curve expects the function you give it to return a vector if the input argument is a vector.
This is clearly documented for the argument "expr" of curve.

Your function miBeta returns a scalar when the argument mu is a vector.
Use Vectorize to vectorize it. Like this

  VmiBeta <- Vectorize(miBeta,vectorize.args=c("mu"))
  VmiBeta(c(420,440))

and draw the curve with this

  curve(VmiBeta,xlim=c(370,430), xlab="mu", ylab="L(mu)")


Berend



More information about the R-help mailing list