【问题标题】:How to implement a 2-d (hue x luminance) color scale?如何实现二维(色调 x 亮度)色标?
【发布时间】:2016-08-19 14:42:11
【问题描述】:

这是一个说明问题的玩具data.frame(它的最基本版本,即;稍后会有额外的皱纹):

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)

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

这个可视化问题特别具有挑战性的方面是图例必须是二维颜色grid(而不是一维颜色bar),与toxin 变量对应的行和与dose 对应的列(或其转换)。

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

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)

控制(“Z”)毒素的点应该是一个灰色的点。 (如果二维彩色网格图例不包含控制值也没关系,但在这种情况下,应该至少有一个图例可以适当地标识其点。)

总结起来,问题分为三个部分:

  1. 分别用色调和亮度表示毒素和剂量。
  2. 制作二维彩色网格图例。
  3. 图例应确定控制点。

以下是我到目前为止所管理的。

我能想到的解决问题的第一个方面的唯一方法是为每种毒素分配不同的层,并根据剂量使用颜色渐变。

不幸的是,似乎没有办法为每一层指定不同的渐变比例。

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

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

第一层本身看起来很有希望:

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

但是当我添加第二层时...

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

...我收到以下警告:

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

而且,果然,这是我得到的情节:

我还没有找到一种方法来定义不同的图层,每个图层都有自己的色阶。

【问题讨论】:

  • 您的问题似乎有点类似于this question,解决方法是同时使用colorfill 来获得两种不同的配色方案。
  • This question/answer 为每组不同颜色渐变的问题提供了另一种解决方案,尽管它可能没有图例。

标签: r ggplot2


【解决方案1】:

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

df$dose <- factor(df$dose)

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

如果它确实必须是图例的矩阵,您可以自己制作矩阵,然后将它们组合在图上。您将失去一些灵活性,并且需要仔细设置,但这应该可以正常工作(请注意,我使用的是最小主题,因为它似乎最适合传说 - 显然是个人喜好):

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

【讨论】:

  • 嗯。毒素最终成为一个因素?否则,很好的近似值
  • 毒素是一个因素。你是说剂量吗?我故意将其设置为绘图之前的一个因素,以便更容易控制适当的 alpha 水平——如果剂量没有标准化(或者只有更多剂量),最好返回一个数字和一个连续规模。 (另外,谢谢)
  • 哦,我明白了; OP想要色调对应毒素。这似乎是个坏主意(因为毒素看起来真的是连续(对数)规模);我建议library(viridis); ... + scale_colour_viridis(),但这是针对 OP,而不是你
  • @BenBolker:你在说什么?毒素具有值“A”、“B”、“C”、“D”、“Z”。这与它所得到的因素差不多。没有什么“连续(对数)规模”-ish。
【解决方案2】:

此解决方案是对this answer 中给出的解决方案的改编。它并没有真的按照问题的要求去做(大部分解决方案的繁重工作不是由ggplot2 完成的,而且传说并不像它可能的那样清楚),但这可能是对于这个问题,最好使用ggplot2

baseplot <- ggplot(data = df, mapping = aes(x = x, y = y))

palette <- function (name, indices = c(3, 5, 7)) {
  RColorBrewer::brewer.pal(9, name)[indices]
}

colors <- c(as.vector(sapply(c("Reds", "Blues", "Greens", "Purples"), palette)),
            "white")

labels <- mapply(function(toxin, dose) {
                     paste(toxin, as.character(dose), sep = " @ ")
                 },
                 df$toxin, df$dose)

(
  baseplot + geom_point(mapping = aes(color = interaction(dose, toxin)),
                        size = 4)
           + scale_color_manual(name = "toxin @ dose",
                                values = colors,
                                labels = labels)
           + guides(color = guide_legend(nrow = 5, byrow = TRUE))
)

这是输出的样子:

【讨论】:

  • 查看我的答案中的编辑,了解作为矩阵的图例的替代方案。
猜你喜欢
  • 2010-10-18
  • 2014-06-10
  • 2014-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-03
  • 1970-01-01
  • 2018-03-22
相关资源
最近更新 更多