如何合并aes()和aes_string()选项

1l5u6lss  于 2023-03-20  发布在  其他
关注(0)|答案(3)|浏览(110)

假设我有这样一个情节

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

在这里我画了两条线,并为每条线指定了一个颜色组。现在假设我想将变量名动态地指定为字符值,这意味着我需要使用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()指定文字字符值?

0s0u357o

0s0u357o1#

更新: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"))

如果您想在aes_string()中指定一个字符文本值,最简单的方法是使用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的列表。我们可以定义一个函数来合并这些列表。例如,我们可以定义addition

`+.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"))
hfyxw5xn

hfyxw5xn2#

有了 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"))
olqngx59

olqngx593#

作为@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"))

相关问题