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 rangesenter image description here

+3


source to share


1 answer


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)

      

enter image description here

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)

      



enter image description here

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)

      

enter image description here

+4


source







All Articles