如何实现二维(色相x亮度)色阶? [英] How to implement a 2-d (hue x luminance) color scale?

查看:192
本文介绍了如何实现二维(色相x亮度)色阶?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是一个玩具 data.frame ,它解释了这个问题(最基本的版本,也就是后面会有一个额外的皱纹):

  df < -  read.table(textConnection(
)毒素剂量xy
A 1 0.851 0.312
A 10 0.268 0.443
A 100 0.272 0.648
B 1 0.981 0.015
B 10 0.304 0.658
B 100 0.704 0.821
C 1 0.330 0.265
C 10 0.803 0.167
C 100 0.433 0.003
D 1 0.154 0.611
D 10 0.769 0.616
D 100 0.643 0.541
),header = TRUE)

我想绘制这些数据的散点图,其中毒素由点的色调表示,剂量为由它们的亮度来表示(第一次近似,低剂量应该对应于高亮度)。

这个可视化问题的特别具有挑战性的方面是该图例将具有成为二维颜色 grid (而不是一维颜色 bar ),其中行对应于 toxin 变量,并且对应的列至剂量(或其转换)。

上面提到的额外皱纹是数据实际包含一个对照观察,其中剂量与所有其他剂量不同(注意下面的毒素行=Z):

  df < -  read.table(textConnection(
毒素剂量xy
A 1 0.851 0.312
A 10 0.268 0.443
A 100 0.272 0.648
B 1 0.981 0.015
B 10 0.304 0.658
B 100 0.704 0.821
C 1 0.330 0.265
C 10 0.803 0.167
C 100 0.433 0.003
D 1 0.154 0.611
D 10 0.769 0.616
D 100 0.643 0.541
Z 0.001 0.309 0.183
),header = TRUE)

控制点(Z)毒素应该是单个灰点。 (如果2-d颜色网格图例不包含控制值,则可以,但在这种情况下,至少应该有一个图例适当地标识它的点。)



总之,问题有三个部分:


  1. 分别用色调和亮度表示毒素和剂量。

  2. 创建2-d颜色网格图例。

  3. 图例应标识控制点。






以下是我迄今为止所管理的内容。



我能想到解决这个问题的唯一方法问题的第一个方面是为每个毒素分配一个不同的层,并使用基于剂量的颜色梯度。

不幸的是,似乎没有一个



更具体地说,我首先定义以下内容:

<$ p

色彩< - RColorBrewer :: brewer.pal(4,Set1)

梯度< - 函数(hue_index){
scale_color_gradient(high = hues [hue_index],
low =white,
trans =log,
limits = c(0.1,100) ,
breaks = c(1,10,100))
}

baseplot < - ggplot(mapping = aes(x = x,y = y,color = dose ))

第一层看起来很有前景:

 
baseplot
+ geom_point(data = subset(df,toxin ==A),size = 4)
+ gradient(1)



我还没有找到一种方法来定义各自拥有自己的图层color scale。

解决方案

它是否必须是传说的网格?如果你愿意有一个毒素图例(颜色)和第二个剂量图例(alpha),你可以使用这个(并且设置你的颜色/填充值对你的数据有意义)

  df $ dose < - 因子(df $剂量)

ggplot(
df
,aes x = x,y = y
,col =毒素
,alpha =剂量)
)+
geom_point(size = 4)



如果真的必须作为图例的矩阵,你可以自己制作矩阵,然后将它们合并到图中。你会失去一些灵活性,并需要仔细设置的东西,但这应该一般工作(请注意,我使用最小的主题,因为它似乎最好的传说 - 显然是个人喜好):

  theme_set(theme_minimal())

mainPlot< -
ggplot(
df
,aes(x = x,y = y
,col =毒素
,alpha =剂量)
)+
geom_point(size = 4)

mainPlot


allLevels< -
expand.grid(toxin = levels(df $ toxin)
,dose = levels(df $ dose))

legendPlot < -
ggplot(
allLevels
,aes(x =毒素,y =剂量
,col =毒素
,alpha =剂量)
)+
geom_point(size = 4)

legendPlot



library(gridExtra)

grid.arrange(
mainPlot +
theme(legend.position =none)
,legendPlot +
theme(legend.position =none) +
ggtitle(Legend)
,layout_matrix =
矩阵(c(1,1,1,NA,2,NA)
,ncol = 2)
,widths = c (2,1)
,heights = c(1,2,1)


Here's a toy data.frame that illustrates the problem (the most basic version thereof, that is; there will be an additional wrinkle later on):

df <- read.table(textConnection(
"toxin  dose    x   y
A   1   0.851   0.312
A   10  0.268   0.443
A   100 0.272   0.648
B   1   0.981   0.015
B   10  0.304   0.658
B   100 0.704   0.821
C   1   0.330   0.265
C   10  0.803   0.167
C   100 0.433   0.003
D   1   0.154   0.611
D   10  0.769   0.616
D   100 0.643   0.541
"), header = TRUE)

I want to make a scatterplot of these data in which the toxin is indicated by the hue of the points, and the dose is indicated by their luminance (to a first approximation, a low dose should correspond to a high luminance).

The particularly challenging aspect of this visualization problem is that the legend would have to be a 2-dimensional color grid (rather than a 1-dimensional color bar), with the rows corresponding to the toxin variable and the columns corresponding to dose (or a transform thereof).

The extra wrinkle I alluded to above is that the data actually includes one control observation, where the dose is different from all the other ones (note the row with toxin = "Z", below):

df <- read.table(textConnection(
"toxin  dose    x   y
A   1   0.851   0.312
A   10  0.268   0.443
A   100 0.272   0.648
B   1   0.981   0.015
B   10  0.304   0.658
B   100 0.704   0.821
C   1   0.330   0.265
C   10  0.803   0.167
C   100 0.433   0.003
D   1   0.154   0.611
D   10  0.769   0.616
D   100 0.643   0.541
Z   0.001   0.309   0.183
"), header = TRUE)

The point for the control ("Z") toxin should be a single gray dot. (It's OK if the 2-d color grid legend does not include the control value, but in this case there should be at least one legend that identifies its point appropriately.)

In summary, the problem has three parts:

  1. Represent toxin and dose by hue and luminance, respectively.
  2. Make a 2-d color grid legend.
  3. Legends should identify the control point.


Below is what I've managed so far.

The only way I can think of to solve the first aspect of the problem would be to devote a different layer to each toxin, and use a color gradient based on the dose.

Unfortunately, there does not seem to be a way to specify a different gradient scale for each layer.

More specifically, I first define the following:

library(ggplot2)

hues <- RColorBrewer::brewer.pal(4, "Set1")

gradient <- function (hue_index) {
  scale_color_gradient(high = hues[hue_index],
                       low = "white",
                       trans = "log",
                       limits = c(0.1, 100),
                       breaks = c(1, 10, 100))
}

baseplot <- ggplot(mapping = aes(x = x, y = y, color = dose))

The first layer, by itself, looks promising:

(
 baseplot
          + geom_point(data = subset(df, toxin == "A"), size = 4)
          + gradient(1)
)

But when I add the second layer...

(
 baseplot
          + geom_point(data = subset(df, toxin == "A"), size = 4)
          + gradient(1)
          + geom_point(data = subset(df, toxin == "B"), size = 4)
          + gradient(2)
)

...I get the following warning:

Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.

And, sure enough, this is the plot I get:

I have not been able to find a way to define different layers each with its own color scale.

解决方案

Does it have to be a grid for the legend? If you are willing to have one legend for toxin (color) and a second legend for dose (alpha), you could use this (and set your colors/fills to what makes sense for your data)

df$dose <- factor(df$dose)

ggplot(
  df
  , aes(x = x, y = y
        , col = toxin
        , alpha = dose)
) +
  geom_point(size = 4)

If it really must be a matrix for the legend, you could do make the matrix yourself, then combine them on the plot. You will lose some flexibility, and will need to carefully set things, but this should work in general (note that I am using the minimal theme as it seems best for the legend -- obviously personal preference):

theme_set(theme_minimal())

mainPlot <-
  ggplot(
    df
    , aes(x = x, y = y
          , col = toxin
          , alpha = dose)
  ) +
  geom_point(size = 4)

mainPlot


allLevels <-
  expand.grid(toxin = levels(df$toxin)
              , dose = levels(df$dose))

legendPlot <-
  ggplot(
    allLevels
    , aes(x = toxin, y = dose
          , col = toxin
          , alpha = dose)
  ) +
  geom_point(size = 4)

legendPlot



library(gridExtra)

grid.arrange(
  mainPlot +
    theme(legend.position = "none")
  , legendPlot +
    theme(legend.position = "none") +
    ggtitle("Legend")
  , layout_matrix =
    matrix(c(1,1,1,NA,2,NA)
           , ncol = 2)
  , widths=c(2,1)
  , heights = c(1,2,1)
  )

这篇关于如何实现二维(色相x亮度)色阶?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆