将带有美元符号 ($) 的变量与 facet_grid() 或 facet_wrap() 组合传递给 aes() 时出现问题
Posted
技术标签:
【中文标题】将带有美元符号 ($) 的变量与 facet_grid() 或 facet_wrap() 组合传递给 aes() 时出现问题【英文标题】:Issue when passing variable with dollar sign notation ($) to aes() in combination with facet_grid() or facet_wrap() 【发布时间】:2015-12-09 04:30:42 【问题描述】:我目前正在 ggplot2 中为一个项目进行一些分析,偶然发现了一些(对我而言)我无法解释的奇怪行为。当我写aes(x = cyl, ...)
时,如果我使用aes(x = mtcars$cyl, ...)
传递相同的变量,情节看起来会有所不同。当我删除facet_grid(am ~ .)
时,两个图表再次相同。下面的代码是根据我的项目中生成相同行为的代码建模的:
library(dplyr)
library(ggplot2)
data = mtcars
test.data = data %>%
select(-hp)
ggplot(test.data, aes(x = test.data$cyl, y = mpg)) +
geom_point() +
facet_grid(am ~ .) +
labs(title="graph 1 - dollar sign notation")
ggplot(test.data, aes(x = cyl, y = mpg)) +
geom_point()+
facet_grid(am ~ .) +
labs(title="graph 2 - no dollar sign notation")
这是图1的图片:
这是图2的图片:
我发现我可以使用 aes_string
而不是 aes
来解决这个问题,并将变量名作为字符串传递,但我想了解为什么 ggplot 会这样。与facet_wrap
类似的尝试也会出现此问题。
【问题讨论】:
简短的回答是:从不在aes()
中使用$
^_^ 今天我的图表突然看起来很奇怪,我感到震惊之后,我不会再这样做了。我仍然想了解发生了什么,因为我以前从未遇到过这个问题/行为。
当 ggplot 构建绘图时,如果将每一层的数据集分成组,由美学和刻面定义。为了使此分组可靠,您需要变量源自单个 data.frame,否则 ggplot 可能最终会为分面因子和映射的其余部分使用不同的顺序。
hmm,但无论我写的是 aes(x = cyl, ...) 还是 aes(x = test.data$cyl ,...)? test.data 是我传递给 ggplot 的 data.frame,它包含所有变量。我哪里错了?非常感谢您的快速回复!
这里的重点是,因为 ggplot 使用非标准评估技术,并且 R 的环境和范围系统可能很复杂,所以当您在此处使用 $ 时,您提供的可能是令人困惑的信息,这将导致 ggplot 无法预测地响应。出错的方式多种多样、复杂且通常不直观。
【参考方案1】:
tl;dr
永远不要在aes()
中使用[
或$
。
考虑这个说明性示例,其中刻面变量f
故意相对于x
以不明显的顺序排列
d <- data.frame(x=1:10, f=rev(letters[gl(2,5)]))
现在对比一下这两个图会发生什么,
p1 <- ggplot(d) +
facet_grid(.~f, labeller = label_both) +
geom_text(aes(x, y=0, label=x, colour=f)) +
ggtitle("good mapping")
p2 <- ggplot(d) +
facet_grid(.~f, labeller = label_both) +
geom_text(aes(d$x, y=0, label=x, colour=f)) +
ggtitle("$ corruption")
我们可以通过查看 ggplot2 内部为每个面板创建的 data.frame 来更好地了解正在发生的事情,
ggplot_build(p1)[["data"]][[1]][,c("x","PANEL")]
x PANEL
1 6 1
2 7 1
3 8 1
4 9 1
5 10 1
6 1 2
7 2 2
8 3 2
9 4 2
10 5 2
ggplot_build(p2)[["data"]][[1]][,c("x", "PANEL")]
x PANEL
1 1 1
2 2 1
3 3 1
4 4 1
5 5 1
6 6 2
7 7 2
8 8 2
9 9 2
10 10 2
第二个图有错误的映射,因为当 ggplot 为每个面板创建一个 data.frame 时,它会以“错误”的顺序选择 x 值。
这是因为$
的使用打破了要映射的各种变量之间的联系(ggplot 必须假定它是一个自变量,据它所知,它可能来自任意的、断开连接的源)。由于此示例中的 data.frame 未根据因子 f
排序,因此每个面板内部使用的子集 data.frames 假定顺序错误。
【讨论】:
非常感谢您的帮助!你的例子太棒了! 这个问题已经在ggplot2 v3.0.0.9000
修复以上是关于将带有美元符号 ($) 的变量与 facet_grid() 或 facet_wrap() 组合传递给 aes() 时出现问题的主要内容,如果未能解决你的问题,请参考以下文章