Color gamut standardization, persp () graphics in panel, R
I am creating a panel with several persp plots, each showing a range of data generated by setting predictor variables in a complex regression model. I want my 3D surface to be color coded with my z variable, which I was able to do quite easily. How do I take this color scale and make it span the range of all z values ββthat will be represented by all plots in my pane so that the color scale can be compared between multiple persp plots?
#colorized z scale, only a smidge modified from http://www.inside-r.org/r-doc/graphics/persp
par(bg = "white")
par(mfrow=c(1,2))
x <- seq(-1.95, 1.95, length = 30)
y <- seq(-1.95, 1.95, length = 35)
z1 <- outer(x, y, function(a, b) a*b^2)
nrz <- nrow(z1)
ncz <- ncol(z1)
# Create a function interpolating colors in the range of specified colors
jet.colors <- colorRampPalette( c("blue", "green") )
# Generate the desired number of colors from this palette
nbcol <- 100
color <- jet.colors(nbcol)
# Compute the z-value at the facet centres
zfacet <- z1[-1, -1] + z1[-1, -ncz] + z1[-nrz, -1] + z1[-nrz, -ncz]
# Recode facet z-values into color indices
facetcol <- cut(zfacet, nbcol)
persp(x, y, z1, zlim=c(-8, 10.5), col = color[facetcol], phi = 30, theta = -30)
#zlim added to encompass combined ranges of z1 and z2
#exact same code, with different values of z
x <- seq(-1.95, 1.95, length = 30)
y <- seq(-1.95, 1.95, length = 35)
z2 <- outer(x, y, function(a, b) a*b^2+3)
nrz <- nrow(z2)
ncz <- ncol(z2)
# Create a function interpolating colors in the range of specified colors
jet.colors <- colorRampPalette( c("blue", "green") )
# Generate the desired number of colors from this palette
nbcol <- 100
color <- jet.colors(nbcol)
# Compute the z-value at the facet centres
zfacet <- z2[-1, -1] + z2[-1, -ncz] + z2[-nrz, -1] + z2[-nrz, -ncz]
# Recode facet z-values into color indices
facetcol <- cut(zfacet, nbcol)
persp(x, y, z2, zlim=c(-8, 10.5), col = color[facetcol], phi = 30, theta = -30)
#zlim added to encompass combined ranges of z1 and z2
#comparing the values, we see that there different, overlapping scales from z1 and z2
summary(as.vector(z1))
summary(as.vector(z2))
So when you look at the two z2 plots, you see that they are on different scales, sort of. It would be much clearer if I could get this color gamut to cover the z1 and z2 ranges
source to share
You can concatenate two vectors (matrices) of z values ββbefore cutting, and then refer to the corresponding subset of the resulting (cut) vector when specifying a color.
color <- jet.colors(nbcol)
z1facet <- z1[-1, -1] + z1[-1, -ncz] + z1[-nrz, -1] + z1[-nrz, -ncz]
z2facet <- z2[-1, -1] + z2[-1, -ncz] + z2[-nrz, -1] + z2[-nrz, -ncz]
facetcol <- cut(c(z1facet, z2facet), nbcol)
persp(x, y, z1, zlim=c(-8, 10.5),
col=color[facetcol[seq_along(z1facet)]],
phi=30, theta=-30)
persp(x, y, z2, zlim=c(-8, 10.5),
col=color[facetcol[-seq_along(z1facet)]],
phi=30, theta=-30)
Alternatively, use lattice::wireframe
which might be easier, especially when working with many surface plots:
library(lattice)
# First, create a named list of the surface matrices.
L <- list(z1=z1, z2=z2)
# Iterate over the elements of L, creating data.frames with row number,
# column number, and cell value, as well as matrix name (i.e. name of
# the element of L).
dat <- do.call(rbind, lapply(seq_along(L), function(i) {
setNames(data.frame(which(!is.na(L[[i]]), arr.ind=TRUE),
c(L[[i]]), names(L)[i]),
c('x', 'y', 'z', 'g'))
}))
# Plot with wireframe, faceting by `g` (the matrix name).
wireframe(z ~ x + y|g, data=dat, drape=TRUE, col.regions=color)
Adjust screen
and distance
as desired to get the look, for example:
wireframe(z ~ x + y|g, data=dat, drape=TRUE, col.regions=color,
screen=list(z=30, x=-60), distance=0.5)
source to share