Как можно смешать 2 или более цветовых палитры, чтобы показать комбинированное цветовое значение

Я пытаюсь создать график, где цвет представляет собой комбинацию нескольких значений. В приведенном ниже примере я применяю увеличивающиеся значения для красного, связанные с координатой x, и увеличивающие значения для синего, связанные с координатой y.

#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()

введите здесь описание изображения

Результат технически правильный в том смысле, что при x = 1 и y = 10 смешивание цветов «белый» и «синий» соответственно возвращает более светлый оттенок синего. Однако я бы предпочел, чтобы эта позиция выглядела такой же «синей», как самый темно-синий цвет полосы y. Я предполагаю, что для этого потребуется использовать прозрачность для более низких значений, а не белый цвет. Есть ли у кого-нибудь предложения о том, как это можно реализовать? Добавление двух цветов, включая их прозрачность, мне не по силам... Я подумал, можно ли использовать значение прозрачности в качестве взвешивания на этапе смешивания?

Спасибо за вашу помощь.


person Marc in the box    schedule 02.08.2012    source источник


Ответы (1)


Поскольку я больше знаком с ggplot, я покажу решение с использованием ggplot. Это имеет дополнительное преимущество: поскольку код ggplot очень прост, мы можем сосредоточить обсуждение на теме управления цветом, а не на коде R.

  1. Начните с использования expand.grid для создания фрейма данных dat, содержащего сетку красных и синих входных значений.
  2. Используйте функцию rgb() для создания сочетания цветов и назначьте его dat$mix.
  3. Участок.

Код:

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()

введите здесь описание изображения


Вы заметите, что цветовая шкала отличается от предложенной вами, но, возможно, более интуитивно понятна.

При смешении света отсутствие какого-либо цвета дает черный цвет, а наличие всех цветов дает белый.

На это ясно указывает сюжет, интерпретация которого мне кажется довольно интуитивной.

person Andrie    schedule 02.08.2012
comment
+1 Спасибо Андре - это довольно интуитивно понятно. Тоже очень компактный код. Легко ли вам будет добавить к такому сюжету соответствующие цветовые гаммы? Думаю, я думал, что субтрактивная цветовая модель типа Cyan-Magenta-Yellow (т. е. равная белому, когда цвета не применяются) может быть лучше для печати, чем аддитивная цветовая модель RGB. - person Marc in the box; 02.08.2012
comment
@Marcinthebox Я подозреваю, что любую попытку смешивания двух элементов в одну цветовую шкалу будет довольно сложно интерпретировать. Что вы пытаетесь заговорить? Можете ли вы вместо этого использовать какую-то другую эстетику, например. размер или форма для обозначения второго элемента? - person Andrie; 02.08.2012
comment
Я думал об использовании такого графика для представления трех концентраций питательных веществ в поверхностных водах (т.е. пространственно). Я надеялся, что такая карта может быть интуитивным способом увидеть эти пространственные закономерности. Я предполагал, что соответствующий цветовой ключ будет тройным графиком, показывающим цветовой градиент для трех концентраций питательных веществ. - person Marc in the box; 02.08.2012
comment
Вместо этого я бы предложил вам использовать фасеты. Я нахожу три сюжета совершенно запутанными и неинтуитивными. Если вы затем добавите к этому потенциально запутанное цветовое сочетание, все станет еще хуже. Три карты, расположенные рядом, каждая из которых демонстрирует уровни определенного питательного вещества, должно быть намного легче интерпретировать. - person Andrie; 02.08.2012