Curves, Surfaces, and Colors

Statistical Computing, 36-350

Friday September 23, 2016

Drawing a curve

To draw a curve of a function, use curve()

curve(x^3) # Default is to plot between 0 and 1

curve(x^3, from=-3, to=3)

curve(x^3, from=-3, to=3, lwd=3, col="red")

Adding a curve to an existing plot

To add a curve to an existing plot, use curve() with add=TRUE

n = 50
set.seed(0)
x = sort(runif(n, min=-2, max=2))
y = x^3 + rnorm(n)
plot(x, y)
curve(x^3, lwd=3, col="red", add=TRUE) # Note: the x argument here and the x vector we defined above are different!

Adding a rug to an existing plot

To add a rug to an existing plot (just tick marks, for where the x points occur), use rug()

plot(x, y)
curve(x^3, lwd=3, col="red", add=TRUE) 
rug(x)

Drawing a surface

To draw a surface, use surface(), available at http://www.stat.cmu.edu/~ryantibs/statcomp-F16/surface.R. (This is a function written by your instructor, relying on the built-in persp() function)

source("http://www.stat.cmu.edu/~ryantibs/statcomp-F16/surface.R")
surface(x^3 + y^3)

surface(x^3 + y^3, from.x=-3, to.x=3, from.y=-3, to.y=3)

surface(x^3 + y^3, from.x=-3, to.x=3, from.y=-3, to.y=3,
        theta=25, phi=15, col=terrain.colors(30), 
        ticktype="detailed", mar=c(2,2,2,2))

Adding points to a surface

To add points to a surface, save the output of surface(). Then use trans3d(), to transform (x,y,z) coordinates to (x,y) coordinates that you can pass to points()

persp.mat = surface(x^3 + y^3, from.x=-3, to.x=3, from.y=-3, to.y=3,
                    theta=25, phi=15, col=rgb(0,0,1,alpha=0.2),
                    ticktype="detailed", mar=c(2,2,2,2))

n = 500
x = runif(n, -3, 3)
y = runif(n, -3, 3)
z = x^3 + y^3 + 5*rnorm(n)

xy.list = trans3d(x, y, z, persp.mat)
points(xy.list, pch=19)

Color palettes

Color palettes are functions for creating vectors of contiguous colors, like gray.colors(), rainbow(), heat.colors(), terrain.colors(), topo.colors(), cm.colors(). Given a number n, each of these functions just returns a vector of colors (names, stored as strings) of length n

n = 50
plot(0, 0, type="n", xlim=c(1,n), ylim=c(1,6))
points(1:n, rep(1,n), col=gray.colors(n), pch=19)
points(1:n, rep(2,n), col=rainbow(n), pch=19)
points(1:n, rep(3,n), col=heat.colors(n), pch=19)
points(1:n, rep(4,n), col=terrain.colors(n), pch=19)
points(1:n, rep(5,n), col=topo.colors(n), pch=19)
points(1:n, rep(6,n), col=cm.colors(n), pch=19)

Creating a custom color palette

To create a custom palette, that interpolates between a set of base colors, colorRampPalette()

cust.colors = colorRampPalette(c("red","purple","darkgreen"))
class(cust.colors)
## [1] "function"
plot(1:n, rep(1,n), col=cust.colors(n), pch=19)

Coloring points by value

Coloring points according to the value of some variable can just be done with a bit of indexing, and the tools you already know about colors

# Function to retrieve a color according to a value
# - val: the value in question
# - lim: a vector of length 2, lower and upper limits for possible values
# - col.vec: the color vector to choose from
get.col.from.val = function(val, lim, col.vec) {
  col.vec[(val-lim[1])/(lim[2]-lim[1]) * (length(col.vec)-1) + 1]
}

# Let's color points according to y value
col.vec = heat.colors(30)
lim = c(-1, 1)
theta = seq(0, 6*pi, length=200)

plot(theta, sin(theta), type="o", pch=19, 
     col=get.col.from.val(sin(theta), lim, col.vec))

Another example

persp.mat = surface(x^3 + y^3, from.x=-3, to.x=3, from.y=-3, to.y=3,
                    theta=25, phi=15, col=rgb(1,1,1,alpha=0.2),
                    ticktype="detailed", mar=c(2,2,2,2))

# Let's color points according to z value
col.vec = terrain.colors(30)
lim = c(min(z), max(z))

xy.list = trans3d(x, y, z, persp.mat)
points(xy.list, pch=19, col=get.col.from.val(z, lim, col.vec))

Another example

# Let's color points according to z value, on a 2d plot
# (this is kind of like a handmade heatmap)
plot(x, y, pch=19, col=get.col.from.val(z, lim, col.vec))