Так как мне нужно будет сделать много разных графиков в 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))
Теперь я создаю модифицированные данные радужной оболочки с именами столбцов, соответствующими желаемой эстетике:
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 и цитатами ( cheatsheet ). [Этот] вопрос был своего рода полезным, но он не решил тот факт, что я хочу вывести эстетику из данных.
В конце концов, я много чего перепробовал и заглянул внутрь. Там я вижу:
exprs <- rlang::enquos(x = x, y = y, ...)
и я думаю, что это причина того, что все попытки, которые я сделал, вроде:
ggplot(iris2, aes(x=x, y=y)) +
geom_point(aes(rlang::quo(expr(color=color))))
не сработало, так как aes пытается "навести порядок" в моих предложениях.
ВОПРОС Есть ли способ динамически передавать аргументы 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)])