使用 cowplot 拼凑图时颜色渐变不正确

Incorrect colour gradient when using cowplot to patch together plots

假设我有一个包含 xy 值的数据集,这些值根据两个变量分组:grpab、或 c,而 subgrpEFG

我想用 y 为所有 grpsubgrp 组合定义的点的颜色针对 x 绘制 y。由于每个 grp 都有非常不同的 y 值,我不能单独使用 facet_grid,因为色标是没有用的。因此,我用自己的比例绘制每个 grp,然后将它们与 cowplot 中的 plot_grid 拼接在一起。我还想使用 scale_colour_gradient2 指定的三点渐变。我的代码如下所示:

# Set RNG seed
set.seed(42)

# Toy data frame
df <- data.frame(x = runif(270), y = runif(270) + rep(c(0, 10, 100), each = 90),
                 grp = rep(letters[1:3], each = 90), subgrp = rep(LETTERS[4:6], 90))

head(df)
#>           x         y grp subgrp
#> 1 0.9148060 0.1362958   a      D
#> 2 0.9370754 0.7853494   a      E
#> 3 0.2861395 0.4533034   a      F
#> 4 0.8304476 0.1357424   a      D
#> 5 0.6417455 0.8852210   a      E
#> 6 0.5190959 0.3367135   a      F

# Load libraries
library(cowplot)
library(ggplot2)
library(dplyr)

# Plotting list
g_list <- list()

# Loop through groups 'grp'
for(i in levels(df$grp)){
  # Subset the data
  df_subset <- df %>% filter(grp == i)
  
  # Calculate the midpoint
  mp <- mean(df_subset$y)
  
  # Print midpoint
  message("Midpoint: ", mp)
  
  g <- ggplot(df_subset) + geom_point(aes(x = x, y = y, colour = y))
  g <- g + facet_grid(. ~ subgrp) + ggtitle(i)
  g <- g + scale_colour_gradient2(low = "blue", high = "red", mid = "yellow", midpoint = mp)
  g_list[[i]] <- g
}
#> Midpoint: 0.460748857570191
#> Midpoint: 10.4696476330981
#> Midpoint: 100.471083269571

plot_grid(plotlist = g_list, ncol = 1)

reprex package (v0.2.1)

于 2019-04-17 创建

在此代码中,我将颜色渐变的中点指定为每个 grpy 的平均值。我打印它并验证它是否正确。是的。

我的问题:为什么前两个图的色标不正确?

尽管对数据进行了子集化,但似乎每个 grp 都应用了相同的范围。如果我将 for(i in levels(df$grp)){ 替换为 for(i in levels(df$grp)[1]){,则色阶对于生成的单个图是正确的。


更新

好吧,这很奇怪。在 g_list[[i]] <- g 之前插入 ggplot_build(g)$data[[1]]$colour 可以解决问题。 但是,为什么?

长话短说,您正在创建未评估的承诺,然后在原始数据消失时评估它们。如果您使用适当的函数式编程风格而不是过程代码,通常可以避免这个问题。即,定义一个完成工作的函数,然后为循环使用一个应用函数。

set.seed(42)

# Toy data frame
df <- data.frame(x = runif(270), y = runif(270) + rep(c(0, 10, 100), each = 90),
                 grp = rep(letters[1:3], each = 90), subgrp = rep(LETTERS[4:6], 90))

library(cowplot)
library(ggplot2)
library(dplyr)

# Loop through groups 'grp'
g_list <- lapply(
  levels(df$grp), 
  function(i) {
    # Subset the data
    df_subset <- df %>% filter(grp == i)

    # Calculate the midpoint
    mp <- mean(df_subset$y)

    # Print midpoint
    message("Midpoint: ", mp)

    g <- ggplot(df_subset) + geom_point(aes(x = x, y = y, colour = y))
    g <- g + facet_grid(. ~ subgrp) + ggtitle(i)
    g <- g + scale_colour_gradient2(low = "blue", high = "red", mid = "yellow", midpoint = mp)
    g
  }
)
#> Midpoint: 0.460748857570191
#> Midpoint: 10.4696476330981
#> Midpoint: 100.471083269571

plot_grid(plotlist = g_list, ncol = 1)

reprex package (v0.2.1)

于 2019-04-17 创建