Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
295 views
in Technique[技术] by (71.8m points)

r - How can one mix 2 or more color palettes to show a combined color value

I'm trying to create a plot where color represents the combination of several values. In the example below, I am applying increasing values for red associated with the x-coordinate and increasing values for blue in associated with the y-coordinate.

#required function 'val2col' from: http://www.menugget.blogspot.de/2011/09/converting-values-to-color-levels.html

val2col<-function(z, zlim, col = heat.colors(12), breaks){
 if(!missing(breaks)){
  if(length(breaks) != (length(col)+1)){stop("must have one more break than colour")}
 }
 if(missing(breaks) & !missing(zlim)){
  zlim[2] <- zlim[2]+c(zlim[2]-zlim[1])*(1E-3)#adds a bit to the range in both directions
  zlim[1] <- zlim[1]-c(zlim[2]-zlim[1])*(1E-3)
  breaks <- seq(zlim[1], zlim[2], length.out=(length(col)+1)) 
 }
 if(missing(breaks) & missing(zlim)){
  zlim <- range(z, na.rm=TRUE)
  zlim[2] <- zlim[2]+c(zlim[2]-zlim[1])*(1E-3)#adds a bit to the range in both directions
  zlim[1] <- zlim[1]-c(zlim[2]-zlim[1])*(1E-3)
  breaks <- seq(zlim[1], zlim[2], length.out=(length(col)+1))
 }
 colorlevels <- col[((as.vector(z)-breaks[1])/(range(breaks)[2]-range(breaks)[1]))*(length(breaks)-1)+1] # assign colors to heights for each point
 colorlevels
}


#data
x <- seq(100)
y <- seq(100)
grd <- expand.grid(x=x,y=y)

#assign colors to grd levels
pal1 <- colorRampPalette(c("white", rgb(1,0,0)), space = "rgb")
col1 <- val2col(x, col=pal1(10))
pal2 <- colorRampPalette(c("white", rgb(0,0,1)), space = "rgb")
col2 <- val2col(y, col=pal2(10))
col3 <- NA*seq(nrow(grd))
for(i in seq(nrow(grd))){
    xpos <- grd$x[i]
    ypos <- grd$y[i]
    coltmp <- (col2rgb(col1[xpos])/2) + (col2rgb(col2[ypos])/2)
    col3[i] <- rgb(coltmp[1], coltmp[2], coltmp[3], maxColorValue = 255)
}

    #plot
png("2_color_scales.png", width=6, height=4, units="in", res=200)
layout(matrix(c(1,2,3), nrow=1, ncol=3), widths=c(4,1,1), heights=4, respect=T)
par(mar=c(4,4,2,2))
plot(grd,col=col3, pch=19)
par(mar=c(4,0,2,5))
image(x=1, y=x, z=t(as.matrix(x)), col=pal1(10), xaxt="n", yaxt="n", xlab="", ylab="")
box()
axis(4)
mtext("x", side=4, line=3, cex=0.7)
par(mar=c(4,0,2,5))
image(x=1, y=y, z=t(as.matrix(y)), col=pal2(10), xaxt="n", yaxt="n", xlab="", ylab="")
box()
axis(4)
mtext("y", side=4, line=3, cex=0.7)
dev.off()

enter image description here

The result is technically correct in that when x = 1 and y = 10, the mixing of colors "white" and "blue", respectively, returns the lighter shade of blue. However, I would rather like this position to look as "blue" as the darkest blue of the y color bar. I imagine this would require one to use transparency for lower values rather than the color white. Does anyone have suggestions on how this might be accomplished? Adding two colors, including their transparency, is beyond me... I thought one might be able to use the transparency value as a weighting in the mixing step?

Thanks for your help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Since I'm more familiar with ggplot, I'll show a solution using ggplot. This has the side benefit that, since the ggplot code is very simple, we can focus the discussion on the topic of colour management, rather than R code.

  1. Start by using expand.grid to create a data frame dat containing the grid of red and blue input values.
  2. Use the function rgb() to create the colour mix, and assign it to dat$mix
  3. Plot.

The code:

dat <- expand.grid(blue=seq(0, 100, by=10), red=seq(0, 100, by=10))
dat <- within(dat, mix <- rgb(green=0, red=red, blue=blue, maxColorValue=100))

library(ggplot2)
ggplot(dat, aes(x=red, y=blue)) + 
  geom_tile(aes(fill=mix), color="white") + 
  scale_fill_identity()

enter image description here


You will notice that the colour scale is different from what you suggested, but possibly more intuitive.

When mixing light, absence of any colour yields black, and presence of all colours yields white.

This is clearly indicated by the plot, which I find rather intuitive to interpret.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...