使用 cowplot 拼凑图时颜色渐变不正确
Posted
技术标签:
【中文标题】使用 cowplot 拼凑图时颜色渐变不正确【英文标题】:Incorrect colour gradient when using cowplot to patch together plots 【发布时间】:2019-09-07 19:16:57 【问题描述】:假设我有一个数据集,其中包含根据两个变量分组的 x
和 y
值:grp
是 a
、b
或 c
,而 subgrp
是 @987654335 @、F
或 G
。
a
在 [0, 1] 中有 y
值
b
在 [10, 11] 中有 y
值
c
在 [100, 101] 中有 y
值。
我想用y
为所有grp
和subgrp
组合定义的点颜色绘制y
和x
。由于每个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 年 4 月 17 日创建
在这段代码中,我将颜色渐变的中点指定为每个grp
的y
的平均值。我打印并验证它是否正确。是的。
我的问题:为什么前两个图的色阶不正确?
尽管对数据进行了子集化,但似乎对每个 grp
应用了相同的范围。如果我将for(i in levels(df$grp))
替换为for(i in levels(df$grp)[1])
,则生成的单个图的色标是正确的。
更新
好吧,这很奇怪。在g_list[[i]] <- g
之前插入ggplot_build(g)$data[[1]]$colour
可以解决问题。 但是,为什么?
【问题讨论】:
这通常会出现循环和ggplot2。我不确定您的确切情况,但这可能与在图中评估变量时有关。见解释here和信息here @aosmith 这真的很有趣。那么,大概ggplot_build(g)$data[[1]]$colour
强制评估并因此保留应有的颜色?似乎另一种选择是 print
不可见地块:invisible(print(g))
就在 g_list[[i]] <- g
之前。
这是我的猜测。我喜欢将数据集按组拆分为列表然后循环遍历数据集以使用lapply()
/purrr::map()
制作许多 ggplot2 图的方法之一是它避免了一些这个。
@aosmith 好东西。我会试试的。感谢您的帮助。
我在循环和 ggplot 方面遇到过类似情况,答案是,ggplot 存在局部变量问题。我觉得这里有点像。仍然不确定为什么 ggplot 会这样。 my old question
【参考方案1】:
长话短说,您正在创建未经评估的承诺,然后在原始数据消失时对其进行评估。如果您使用正确的函数式编程风格而不是过程代码,则通常可以避免此问题。即,定义一个完成工作的函数,然后为循环使用一个应用函数。
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 年 4 月 17 日创建
【讨论】:
考虑by
,比嵌套的lapply
+ split
或lapply
+ levels
或lapply
+ unique
更精简。以上是关于使用 cowplot 拼凑图时颜色渐变不正确的主要内容,如果未能解决你的问题,请参考以下文章