r - 具有从输入数据生成的美学效果的 ggplot

标签 r ggplot2 rlang quosure

由于我需要在 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 试图“确定”我的 quosure(s)。

问题 有没有办法根据数据的内容以动态的方式向 aes 提供参数(所以你事先不知道你需要哪种美学?

如果我的问题不够清楚,最后我做了一些有用的东西,只是我觉得这完全没有必要,因为我不知道/理解正确的方法。所以下面的东西是有效的,是我的想法,但我就是这样。不喜欢的是我不得不修改 aes:

下面的 block 是独立的,可以在没有上面的代码块的情况下执行。
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)])

最佳答案

您可以使用此自定义函数来解析输入数据列名并生成 aes传递给 eval() 的文本字符串.

generateAES <- function(foo) {
    eval(parse(text = paste0("aes(", 
        paste(
            lapply(foo, function(i) paste(i, "=", i)), 
        collapse = ","), 
        ")"
    )))
}

您可以将其用于:
ggplot(iris2, generateAES(colnames(iris2))) +
    geom_point()

或使用管道:
library(magrittr)
iris2 %>%
    ggplot(generateAES(colnames(.))) +
        geom_point()
generateAES输出为 aes像:
Aesthetic mapping: 
* `x`      -> `x`
* `y`      -> `y`
* `colour` -> `color`
* `shape`  -> `shape`

这是从文本字符串 "aes(x = x,y = y,color = color,shape = shape)" 生成的

关于r - 具有从输入数据生成的美学效果的 ggplot,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54293850/

相关文章:

r - 在 R 中,当名称是字符向量的值时,如何通过名称指示参数?

r - 确定满足条件的数据点的数量

r - 用ggplot在对数图中绘制椭圆

r - 创建条形图时的 Ggplot() 图形问题

r - 在 ggplot2 中,如何使多面图具有最小高度并共享相同的刻度?

r - 为什么表达式 LHS 中的 `rlang::sym` 和 `rlang::quo_name` 表现相似?

r - 将单个参数作为 tidyeval 中的点传递

r - 向量 y <- c ("abc"、 "def"、 ""、 "ghi") 中的第三个值是 NULL、NA 还是其他值?

python - 如何正确设置rpy2?

r - ggplot2 - 为数据框的每一列创建一个条形图