 M. Beausoleil -4 years ago 78
R Question

# How can I plot 2 peaks in a 3D graph with different colors in R (using the x-axis, not the Z-axis)?

I want to color two peaks, with different colors, in a 3d plots but it's not working. Most of the help I find is to color by the z-axis, but I want to color just the peaks.

Here is what I got so far: ``````x <- seq(-10, 10, length = 100)
y <- x

norm <- function(x,y, mean1 = 3, var1 =2,mean2 = -3, var2 =2) {
1/sqrt(2*var1^2*1)*exp(-((y-mean2)^2/(2*var2^2))) *
1/sqrt(2*var2^2*1)*exp(-((x-mean2)^2/(2*var1^2)))+
1/sqrt(2*var2^2*1)*exp(-((y-mean1)^2/(2*var2^2))) *
1/sqrt(2*var1^2*1)*exp(-((x-mean1)^2/(2*var1^2)))      }

z <- outer(x, y, norm)
z[is.na(z)] <- 1

rbPal <- colorRampPalette(c('red','blue'))
Col <- rbPal(10)[as.numeric(cut(x = x,breaks = 2))]

persp(x, y, z, col = "blue",
xlab = "",
ylab = "", zlab = "",
theta = 60,
phi = 15,d = 10,
border = border,
zlim=c(0,.2))
``````

Other try, this is closer to what I want, but as you can see, not optimal since the "floor" is overlapping the other peak! ``````norm1 <- function(x,y, mean1 = 3, var1 =2,mean2 = -3, var2 =2) {
1/sqrt(2*var1^2*1)*exp(-((y-mean2)^2/(2*var2^2))) *
1/sqrt(2*var2^2*1)*exp(-((x-mean2)^2/(2*var1^2)))
}
norm2 <- function(x,y, mean1 = 3, var1 =2,mean2 = -3, var2 =2) {
1/sqrt(2*var2^2*1)*exp(-((y-mean1)^2/(2*var2^2))) *
1/sqrt(2*var1^2*1)*exp(-((x-mean1)^2/(2*var1^2)))      }

z1 <- outer(x, y, norm1)
z1[is.na(z1)] <- 1

z2 <- outer(x, y, norm2)
z2[is.na(z1)] <- 1

persp(x, y, z1, col ="red",
xlab = "",
ylab = "", zlab = "",
theta = 60,
phi = 15,d = 10,
border = border,
zlim=c(0,.2))

par(new=TRUE)
red.a = adjustcolor( "blue", alpha.f = .70)
persp(x, y, z2, col ="blue",
xlab = "",
ylab = "", zlab = "",
theta = 60,
phi = 15,d = 10,
border = border,
zlim=c(0,.2))
`````` Jacob Socolar

One approach is to make the full plot as a collage of different pieces. In the code below, I split the plot along the diagonal (in the x-y plane) to give the two peaks different colors. But I think there's nothing stopping you from getting fancier here with different colors for multiple regions of the x-y plane.

``````x <- seq(-10, 10, length = 100)
y <- x

norm <- function(x,y, mean1 = 3, var1 =2,mean2 = -3, var2 =2) {
1/sqrt(2*var1^2*1)*exp(-((y-mean2)^2/(2*var2^2))) *
1/sqrt(2*var2^2*1)*exp(-((x-mean2)^2/(2*var1^2)))+
1/sqrt(2*var2^2*1)*exp(-((y-mean1)^2/(2*var2^2))) *
1/sqrt(2*var1^2*1)*exp(-((x-mean1)^2/(2*var1^2)))      }

z <- outer(x, y, norm)
z[is.na(z)] <- 1

rbPal <- colorRampPalette(c('red','blue'))
Col <- rbPal(10)[as.numeric(cut(x = x,breaks = 2))]

persp(x, y, z, col = "blue",
xlab = "",
ylab = "", zlab = "",
theta = 60,
phi = 15,d = 10,
#  border = border,
zlim=c(0,.2))

z2 <- z
for(i in 1:100){
for(j in 1:(100-i)){
z2[i,j] <- NA
}
}

par(new=T)
graphics::persp(x, y, z2, col = "red",
xlab = "",
ylab = "", zlab = "",
theta = 60,
phi = 15,d = 10,
#  border = border,
zlim=c(0,.2))
``````

Or if you just want the peaks colored (and everything else gray, for example), you could do

``````z3 <- z
z3[z3<.03] <- NA
z4 <- z2
z4[z4<.03] <- NA

persp(x, y, z, col = "gray90",
xlab = "",
ylab = "", zlab = "",
theta = 60,
phi = 15,d = 10,
#  border = border,
zlim=c(0,.2))

par(new=T)
persp(x, y, z3, col = "skyblue1",
xlab = "",
ylab = "", zlab = "",
theta = 60,
phi = 15,d = 10,
#  border = border,
zlim=c(0,.2))

par(new=T)
persp(x, y, z4, col = "indianred1",
xlab = "",
ylab = "", zlab = "",
theta = 60,
phi = 15,d = 10,
#  border = border,