ggplot2 要求 geom_errorbar 中不存在的美学

ggplot2 asking for a non-existent aesthetic in geom_errorbar

我实际上找到了我的问题的答案,但我想知道这是否是一个错误。

假设我有这个:

library(ggplot2)
library(dplyr)
first <-
mtcars %>%
  group_by(vs) %>%
  summarise(mean = mean(mpg),
            lower_ci = mean(mpg) - 2 * sd(mpg),
            upper_ci = mean(mpg) + 2 * sd(mpg))

我可以像这样制作分层图:

ggplot(data = mtcars, aes(x = as.factor(vs))) +
  geom_point(aes(y = mpg), alpha = 0.2) +
  geom_point(data = first, aes(y = mean), colour = "red") +
  geom_errorbar(data = first, aes(ymin = lower_ci, ymax = upper_ci))

很好,没问题。让我们一步步重现剧情。

graph <- ggplot()
graph <- graph + geom_point(alpha = 0.2)
graph <- graph %+% mtcars + aes(x = as.factor(vs), y = mpg)
graph <- graph + geom_point(data = first, aes(x = as.factor(vs), y = mean, colour = "red"))

此时我只需要覆盖需要 xyminymax aes 的误差线。但是,graph 对象在对象的结构中有一个预定义的 y。出于某种原因,如果我添加这个:

graph + geom_errorbar(data = first,
                               aes(x = as.factor(vs), ymin = lower_ci, ymax = upper_ci))

我认为这是正确的方法,它会引发有关 aesthetic 长度的错误。当然,first 数据框的长度是正确的,所以我认为它应该通过全局选项中的 y aesthetic。

如果我添加这个:

graph + geom_errorbar(data = first,
                               aes(x = as.factor(vs), y = NULL, ymin = lower_ci, ymax = upper_ci))

它修复了它并如预期抛出 Warning: Ignoring unknown aesthetics: y

我假设对象的全局选项会识别 geom_errorbar 不需要 y aesthetic。

我是不是遗漏了什么?

Am I missing something here?

没有。您正确地识别了问题;你只是假设还有别的东西。这是一个可能不值得修复的小错误。

I would assume that the global options of the object would recognize that geom_errorbar doesn't require a y aesthetic.

美学是默认继承的(您可以通过设置inherit.aes = FALSE)避免错误),并立即根据可用数据进行检查。如果继承的映射列不可用,因为它不在图层的数据框中,则会引发错误。

这是另一个例子。它与你问题中的那个并没有什么不同,但它使用更常见的 geoms 并且更简单一点:

df1 = data.frame(x1 = 1:2, y1 = 3:4, ty = 'a')
df2 = data.frame(x2 = 1, y2 = 5)

ggplot(df1, aes(x1, y1, linetype = ty)) +
    geom_line() + 
    geom_point(data = df2, aes(x = x2, y = y2))
# Error in eval(expr, envir, enclos) : object 'ty' not found

即使 geom_point 不采用 linetype 美学,因为 df2 中没有名为 ty 的数据列,我们会收到错误消息。如下所示,简单的解决方法是设置 inherit.aes = FALSE:

ggplot(df1, aes(x1, y1, lintype = ty)) +
    geom_line() + 
    geom_point(data = df2, aes(x = x2, y = y2), inherit.aes = FALSE)
## works