将带有美元符号符号 ($) 的变量与 facet_grid() 或 facet_wrap() 组合传递给 aes() 时出现的问题

Issue when passing variable with dollar sign notation ($) to aes() in combination with facet_grid() or facet_wrap()

提问人:Christoph 提问时间:9/13/2015 最后编辑:Jan SchultkeChristoph 更新时间:9/1/2020 访问量:3326

问:

我目前正在 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 的图片:

graph 1 - dollar sign notation

这是图 2 的图片:

graph 2 - no dollar sign notation

我发现我可以使用代替变量名称并将其作为字符串传递来解决这个问题,但我想了解为什么 ggplot 会以这种方式运行。在类似的尝试中也会出现此问题。aes_stringaesfacet_wrap

GGPLOT2 R-常见问题

评论

14赞 baptiste 9/13/2015
简短的回答是:永远不要$aes()
0赞 Christoph 9/13/2015
^_^ 在我今天感到震惊之后,当我的图表突然看起来很奇怪时,我不会再这样做了。我仍然想知道发生了什么,因为我以前从未遇到过这个问题/行为。
1赞 baptiste 9/13/2015
当 ggplot 构建绘图时,如果将每个图层的数据集拆分为组,由美学和刻面定义。为了使这种分组可靠,您需要变量源自单个 data.frame,否则 ggplot 最终可能会对分面因子和映射的其余部分使用不同的顺序。
0赞 Christoph 9/13/2015
嗯,但是无论我写的是 aes(x = cyl, ...) 还是 aes(x = test.data$cyl,...),在这个示例中,变量不是在同一个 data.frame 中吗?test.data 是我传递给 ggplot 的 data.frame,它包含所有变量。我哪里出错了?非常感谢您的快速回复!
3赞 joran 9/13/2015
这里的重点是,由于 ggplot 使用的是非标准的评估技术,并且 R 的环境和范围系统可能很复杂,因此当您在此处使用 $ 时,您将提供可能令人困惑的信息,这将导致 ggplot 做出不可预测的响应。事情可能出错的方式是多种多样的、复杂的,而且通常不直观。

答:

35赞 baptiste 9/13/2015 #1

tl;博士

切勿使用或内部使用。[$aes()


考虑这个说明性示例,其中分面变量故意以不明显的顺序排列fx

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

enter image description here

我们可以通过查看 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 不是根据因子排序的,因此内部用于每个面板的子集 data.frame 假定错误的顺序。$f

评论

1赞 Christoph 9/13/2015
非常感谢您的帮助!你的榜样太棒了!
2赞 Tung 7/15/2018
此问题已在 ggplot2 v3.0.0.9000 中修复