如何结合使用aes()和aes_string()选项?

24
假设我有这样一个图表:
library(ggplot2)
ggplot(mtcars, aes(x=wt)) + ylab("") +
   geom_line(aes(y=mpg, color="one")) + 
   geom_line(aes(y=qsec, color="two")) + 
   scale_color_manual(name="Val", values=c(one="#105B63",two="#BD4932"))

enter image description here

我正在绘制两条线,并为每条线指定一个颜色组。现在假设我想要动态指定变量名称作为字符值,这意味着我需要使用 aes_string()。 如果我尝试这样做:

v1<-"mpg"
v2<-"qsec"
ggplot(mtcars, aes(x=wt)) + ylab("") +
   geom_line(aes_string(y=v1, color="one")) + 
   geom_line(aes_string(y=v2, color="two")) + 
   scale_color_manual(name="Val", values=c(one="#105B63",two="#BD4932"))

我遇到了错误

Error in eval(expr, envir, enclos) : object 'one' not found

因为现在 aes_string() 正试图解析颜色值,而我只想要一个字面字符值。如果我尝试这样做
ggplot(mtcars, aes(x=wt)) + ylab("") +
   geom_line(aes_string(y=v1), aes(color="one")) + 
   geom_line(aes_string(y=v2), aes(color="two")) + 
   scale_color_manual(name="Val", values=c(one="#105B63",two="#BD4932"))

我理解

Error: ggplot2 doesn't know how to deal with data of class uneval

可能是因为该层不知道如何处理两个美学指令。

我该如何组合 aes()aes_string() 美学,或者如何为 aes_string() 指定文字值?

3个回答

38

更新:ggplot >=v3.0 支持整洁评估和 .data 代词。同时使用字符值和文字值的推荐方法是

ggplot(mtcars, aes(x=wt)) + ylab("") +
   geom_line(aes(y=.data[[v1]], color=one)) + 
   geom_line(aes(y=.data[[v2]], color=two)) + 
   scale_color_manual(name="Val", values=c(one="#105B63",two="#BD4932"))

如果您想在中指定字符文字值,最简单的方法是使用shQuote()来引用该值。例如:
ggplot(mtcars, aes(x=wt)) + ylab("") +
   geom_line(aes_string(y=v1, color=shQuote("one"))) + 
   geom_line(aes_string(y=v2, color=shQuote("two"))) + 
   scale_color_manual(name="Val", values=c(one="#105B63",two="#BD4932"))

这是可行的,因为 aes_string() 实际上对每个参数值运行 parse(text=)shQuote() 函数在字符值周围添加引号,以便当您解析该值时,您将获得一个字符值而不是一个符号/名称。比较这两个调用。
class(parse(text="a")[[1]])
# [1] "name"
class(parse(text=shQuote("a"))[[1]])
# [1] "character"

或者你可以考虑合并aes()指令。实际上,aes()函数只是返回一个类为uneval的列表。我们可以定义一个函数来组合/合并这些列表。例如,我们可以定义加法

`+.uneval` <- function(a,b) {
    `class<-`(modifyList(a,b), "uneval")
}

现在我们可以做到

ggplot(mtcars, aes(x=wt)) + ylab("") +
   geom_line(aes_string(y=v1) + aes(color="one")) + 
   geom_line(aes_string(y=v2) + aes(color="two")) + 
   scale_color_manual(name="Val", values=c(one="#105B63",two="#BD4932"))

4
很好,你解决了我甚至没有意识到的一个问题 ;) (+1.5) - BrodieG

12

使用 ggplot2 V3.0.0 版本,变得非常简单:

v1<-"mpg"
v2<-"qsec"
ggplot(mtcars, aes(x=wt)) + ylab("") +
  geom_line(aes(y=!!sym(v1), color="one")) + 
  geom_line(aes(y=!!sym(v2), color="two")) + 
  scale_color_manual(name="Val", values=c(one="#105B63",two="#BD4932"))

10

除了 @MrFlick 的优秀答案之外,您还可以使用 aes_q 并将变量内容转换为 name

ggplot(mtcars, aes(x=wt)) + ylab("") +
  geom_line(aes_q(y=as.name(v1), color="one")) + 
  geom_line(aes_q(y=as.name(v2), color="two")) + 
  scale_color_manual(name="Val", values=c(one="#105B63",two="#BD4932"))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接