我如何组合 aes() 和 aes_string() 选项
How do I combine aes() and aes_string() options
假设我有这样的情节
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()
指定文字字符值?
如果要在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()
函数在您的字符值周围添加引号,这样当您解析该值时,您会得到一个字符值而不是 symbol/name。比较这两个调用
class(parse(text="a")[[1]])
# [1] "name"
class(parse(text=shQuote("a"))[[1]])
# [1] "character"
或者,您可能会考虑合并 aes()
指令。 aes()
函数实际上只是 return 一个 class 为 uneval
的列表。我们可以为 combine/merge 这些列表定义一个函数。例如我们可以定义加法
`+.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"))
作为@MrFlick 出色答案的替代方案,您还可以使用 aes_q
并将变量的内容转换为 name
s:
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"))
使用 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"))
假设我有这样的情节
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()
指定文字字符值?
如果要在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()
函数在您的字符值周围添加引号,这样当您解析该值时,您会得到一个字符值而不是 symbol/name。比较这两个调用
class(parse(text="a")[[1]])
# [1] "name"
class(parse(text=shQuote("a"))[[1]])
# [1] "character"
或者,您可能会考虑合并 aes()
指令。 aes()
函数实际上只是 return 一个 class 为 uneval
的列表。我们可以为 combine/merge 这些列表定义一个函数。例如我们可以定义加法
`+.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"))
作为@MrFlick 出色答案的替代方案,您还可以使用 aes_q
并将变量的内容转换为 name
s:
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"))
使用 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"))