【发布时间】:2019-06-15 01:44:03
【问题描述】:
由于我需要在 R 中制作许多不同的图,因此我试图在准备数据时添加更多逻辑(添加与美学相对应的列名),而在图本身中添加更少的逻辑。
考虑以下默认虹膜图:
library(ggplot2)
library(data.table)
scatter <- ggplot(data=iris, aes(x = Sepal.Length, y = Sepal.Width))
scatter + geom_point(aes(color=Species, shape=Species))
现在我使用与所需美学匹配的列名制作修改后的 iris 数据:
iris2 <- as.data.table(iris)
iris2 <- iris2[,.(x=Sepal.Length, y=Sepal.Width, color=Species,
shape=Species)]
我想以这样一种方式在函数中绘制,它基本上构建以下命令只是稍微动态一些,所以你使用数据中提供的所有美学。
ggplot(data, aes(x=x, y=y)) + geom_point(aes(color=color, shape=shape))
我已经很久没有阅读任何关于非标准评估、表达式和引用的内容了,我注意到rlang 和 quosures (cheatsheet) 有相当多的发展。 [这个]问题有点帮助,但它并没有解决我想从数据中推断出美学的事实。
最后我尝试了很多东西,并查看了aes。在那里我看到了:
exprs <- rlang::enquos(x = x, y = y, ...)
我认为这就是我所做的所有尝试都喜欢的原因:
ggplot(iris2, aes(x=x, y=y)) +
geom_point(aes(rlang::quo(expr(color=color))))
没有成功,因为 aes 正试图 'enquos' 我的 quosure(s)。
QUESTION有没有什么方法可以根据数据的内容以动态的方式向 aes 提供参数(所以你事先不知道你需要哪种美学?
如果我的问题不够清楚,最后我做了一些有用的东西,只是我觉得这完全没有必要,因为我不知道/理解正确的方法。所以下面的东西是有效的,是我的想法,但我就是这样。不喜欢的是我不得不修改aes:
下面的块是独立的,可以在没有上面的代码块的情况下执行。
library(data.table)
library(ggplot2)
library(rlang)
iris2 <- as.data.table(iris)
iris2 <- iris2[,.(x=Sepal.Length, y=Sepal.Width, color=Species, shape=Species)]
myaes <- function (x, y, myquo=NULL, ...) {
exprs <- rlang::enquos(x = x, y = y, ...)
exprs <- c(exprs, myquo)
is_missing <- vapply(exprs, rlang::quo_is_missing, logical(1))
aes <- ggplot2:::new_aes(exprs[!is_missing], env = parent.frame())
ggplot2:::rename_aes(aes)
}
generalPlot <- function(data, f=geom_point,
knownaes=c('color'=expr(color), 'shape'=expr(shape))){
myquo <- list()
for(i in names(knownaes)){
if(i %in% names(data)){
l <- list(rlang::quo(!!knownaes[[i]]))
names(l) <- i
myquo <- c(myquo, l)
}
}
ggplot(data, aes(x=x, y=y)) +
f(myaes(myquo=myquo))
}
generalPlot(iris2[,.(x, y, color)])
generalPlot(iris2[,.(x, y, color, shape)])
【问题讨论】: