1

I am trying to visualize a curve for pollination distribution. I am very new to R so please don't be upset by my stupidity.

llim <- 0
ulim <- 6.29

f <- function(x,y) {(.156812/((2*pi)*(.000005^2)*(gamma(2/.156812)))*exp(-((sqrt(x^2+y^2))/.000005)^.156812))}

integrate(function(y) {
     sapply(y, function(y) {
          integrate(function(x) f(x,y), llim, ulim)$value
          })
     }, llim, ulim)

fv <- Vectorize(f)

curve(fv, from=0, to=1000)

And I get:

Error in y^2 : 'y' is missing
Dreamwalker
  • 3,032
  • 4
  • 30
  • 60
  • 1
    `curve` expects only a one-dimensional function – James Jan 13 '15 at 13:42
  • If this is not possible in R, I have Matlab and Mathematica as well, but I do not know how to code in either of them (at all). Thank you again!!! – Andi Noakes Jan 13 '15 at 13:54
  • Thank you James. Is there another command that I can use to plot this? – Andi Noakes Jan 13 '15 at 13:55
  • You probably want `persp`. – Thomas Jan 13 '15 at 13:58
  • Take a look at this question: http://stackoverflow.com/q/7568356/269476 – James Jan 13 '15 at 13:58
  • It is certainly possible in R. However, can you better explain precisely what you want on your x-axis and y-axis? – Anders Ellern Bilgrau Jan 13 '15 at 14:00
  • I am hoping for Distance from 0 to 1000 meters on my x axis and the probability of pollination (or probability density) on my y axis. I'm glad to hear it is possible in R! I have looked up persp and tried to download it, but apparently do not have the correct version of R for that? I can't find which version I need. I have 2.14.1, 2.14.2, and 3.1.2. – Andi Noakes Jan 13 '15 at 14:15

2 Answers2

1

I'm not quite sure what you're asking to plot. But I know you want to visualise your scalar function of two arguments.

Here are some approaches. First we define your function.

llim <- 0
ulim <- 6.29

f <- function(x,y) {
  (.156812/((2*pi)*(.000005^2)*(gamma(2/.156812)))*exp(-((sqrt(x^2+y^2))/.000005)^.156812))
}

From your title I thought of the following. The function defined below intf integrates your function over the square [0,ul] x [0,ul] and return the value. We then vectorise and plot the integral over the square as a function the length of the side of the square.

intf <- function(ul) {
  integrate(function(y) {
    sapply(y, function(y) {
      integrate(function(x) f(x,y), 0, ul)$value
      })
    }, 0, ul)$value
}
fv <- Vectorize(intf)
curve(fv, from=0, to=1000)

Imgur

If f is a distribution, I guess you can make your (somewhat) nice probability interpretation of this curve. (I.e. ~20 % probability of pollination(?) in the 200 by 200 meter square.)

However, you can also do a contour plot (of the log-transformed values) which illustrate the function we are integrating above:

 logf <- function(x, y) log(f(x, y))
 x <- y <- seq(llim, ulim, length.out = 100)
 contour(x, y, outer(x, y, logf), lwd = 2, drawlabels = FALSE)

Imgur

You can also plot some profiles of the surface:

plot(1, xlim = c(llim, ulim), ylim = c(0, 0.005), xlab = "x", ylab = "f")
y <- seq(llim, ulim, length.out = 6)
for (i in seq_along(y)) {
  tmp <- function(x) f(x, y = y[i])
  curve(tmp, llim, ulim, add = TRUE, col = i)
}
legend("topright", lty = 1, col = seq_along(y),
       legend = as.expression(paste("y = ",y)))

Imgur

They need to be modified a bit to make them publication worthy, but you get the idea. Lastly, you can do some 3d plots as others have suggested.

EDIT As per your comments, you can also do something like this:

# Define the function times radius (this time with general a and b)
# The default of a and b is as before
g <- function(z, a = 5e-6, b = .156812) {
  z * (b/(2*pi*a^2*gamma(2/b)))*exp(-(z/a)^b)
}

# A function that integrates g from 0 to Z and rotates
# As g is not dependent on the angle we just multiply by 2pi
intg <- function(Z, ...) {
  2*pi*integrate(g, 0, Z, ...)$value
}

# Vectorize the Z argument of intg
gv <- Vectorize(intg, "Z")

# Plot
Z <- seq(0, 1000, length.out = 100) 
plot(Z, gv(Z), type = "l", lwd = 2)
lines(Z, gv(Z, a = 5e-5),         col = "blue", lwd = 2)
lines(Z, gv(Z, b = .150),         col = "red", lwd = 2)
lines(Z, gv(Z, a = 1e-4, b = .2), col = "orange", lwd = 2)

Imgur

You can then plot the curves for the a and b you want. If either is not specified, the default is used. Disclaimer: my calculus is rusty and I just did off this top of my head. You should verify that I've done the rotation of the function around the axis properly.

Anders Ellern Bilgrau
  • 9,928
  • 1
  • 30
  • 37
  • Okay, one more thing you might be able to help me with since you are currently my hero. I am trying to visualize a graph of the cumulative fraction of pollen collected within a circle of radius Z (centered on the maternal parent) by integrating: (b/2pia^2(gamma(2/b))*exp(-(z/a)^b) from theta=0 to theta=2pi and z=0 to z=Z (where Z is the radius of the circle within which the cumulative fraction of pollen has been collected ie. pollination has occurred). a is the scale parameter, b is the shape parameter and z is the sqrt(x^2+y^2). – Andi Noakes Jan 13 '15 at 16:04
  • @AndiNoakes I've edited my answer. Is that what you want? Please do check the maths yourself. – Anders Ellern Bilgrau Jan 13 '15 at 17:07
0

The lattice package has several functions that can help you draw 3 dimensional plots, including wireframe() and persp(). If you prefer not to use a 3d-plot, you can create a contour plot using contour().

Note: I don't know if this is intentional, but your data produces a very large spike in one corner of the plot. This produces a plot that is for all intents flat, with a barely noticable spike in one corner. This is particularly problematic with the contour plot below.

library(lattice)

x <- seq(0, 1000, length.out = 50)
y <- seq(0, 1000, length.out = 50)

First the wire frame plot:

df <- expand.grid(x=x, y=y)
df$z <- with(df, f(x, y))
wireframe(z ~ x * y, data = df)

enter image description here

Next the perspective plot:

dm <- outer(x, y, FUN=f)
persp(x, y, dm)

enter image description here

The contour plot:

contour(x, y, dm)

enter image description here

Andrie
  • 176,377
  • 47
  • 447
  • 496