我有一个函数,可以 Select 性地接受预定义的美学(对于ggplot2).这可以是几种形式之一,包括

mapping <- aes(color = c(cyl, gear))
mapping
# Aesthetic mapping: 
# * `colour` -> `c(cyl, gear)`

或编程为

mapping <- aes(color = c(.data[["cyl"]], .data[["gear"]]))
mapping
# Aesthetic mapping: 
# * `colour` -> `c(.data[["cyl"]], .data[["gear"]])`

(我在这里使用的是color=,但实际上我使用的是group=subgroup=的不同方式.为简单起见,我在这里简化为color=个.)

我的函数不能控制调用者是否或如何定义mapping(默认为NULL),它可以使用符号(第一个例子),也可以使用像.data这样的编程选项之一(第二个例子),但在内部,在我调整/增加数据之后,我需要添加一个变量.

我可以用c结合different美学,比如

mapping <- aes(color = factor(cyl))
othermap1 <- aes(x = mpg, y = disp)
ggplot(mtcars, mapping = aes(!!!c(mapping, othermap1))) +
  geom_path()

(剧情本身并不重要,重要的是它奏效了.)

simple grouped ggplot lines

如果我想给color=的审美增加一个变量,我不知道如何最好地做到这一点.

othermap2 <- aes(color = gear)

我希望能够得到color=的综合效果,结果类似于手册:

ggplot(mtcars, mapping = aes(mpg, disp, color = interaction(cyl, gear))) +
  geom_path()

这完全是程序性的,我更愿意允许用户在调用我的函数时提供一个"真正的"mapping=参数(例如,mapping=aes(...)).

我认为一种可能的方法是要求用户提供一个命名的变量列表,如果他们想要赋值color=,比如mapping=list(group="cyl"),我会在内部增加/合并,然后在内部创建.data[[x]]美学……但我真的更愿意继续允许用户使用mapping=aes(..).

推荐答案

您可以使用一些rlang魔法来操作贴图. 简而言之,我们只是指定新的美学,如果它是不正确的,否则我们创建一个结合这两个表达的新调用.

library(ggplot2)
library(rlang)

combine_mapping <- function(user, fixed, fun = interaction) {
  names(user)  <- standardise_aes_names(names(user))
  names(fixed) <- standardise_aes_names(names(fixed))
  fun <- enexpr(fun)
  for (var in names(fixed)) {
    inject <- quo_get_expr(fixed[[var]])
    if (var %in% names(user)) {
      expr <- quo_get_expr(user[[var]])
      user[[var]] <- call2(fun, !!!list(inject, expr))
    } else {
      user[[var]] <- fixed[[var]]
    }
  }
  user
}

一些演示

user_mapping <- aes(mpg, disp, colour = cyl)

# Case of missing aesthetic
combine_mapping(aes(mpg, disp), aes(colour = cyl))
#> Aesthetic mapping: 
#> * `x`      -> `mpg`
#> * `y`      -> `disp`
#> * `colour` -> `cyl`

# Combining aesthetic
combine_mapping(user_mapping, aes(colour = gear))
#> Aesthetic mapping: 
#> * `x`      -> `mpg`
#> * `y`      -> `disp`
#> * `colour` -> `interaction(gear, cyl)`

# Multiple aesthetics
combine_mapping(user_mapping, aes(colour = gear, x = cty))
#> Aesthetic mapping: 
#> * `x`      -> `interaction(cty, mpg)`
#> * `y`      -> `disp`
#> * `colour` -> `interaction(gear, cyl)`

# Other function to combine
combine_mapping(user_mapping, aes(colour = gear), fun = paste0)
#> Aesthetic mapping: 
#> * `x`      -> `mpg`
#> * `y`      -> `disp`
#> * `colour` -> `paste0(gear, cyl)`

# Works in plot
ggplot(mtcars, combine_mapping(aes(mpg, disp, colour = cyl), aes(colour = gear))) +
  geom_point()

创建于2023-12-22,共reprex v2.0.2

R相关问答推荐

使用R中的gt对R中的html rmarkdown文件进行条件格式设置表的单元格

根据收件箱中的特定值提取列名

在特定Quarto(reveal.js)幻灯片上隐藏徽标

如何通过Docker部署我的shiny 应用程序(多个文件)

自动变更列表

单个轮廓重叠条的单独图例

LOF中的插图短文字幕

使用带有OR条件的grepl过滤字符串

DEN扩展包中的RECT树形图出现异常行为

展开对数比例绘图的轴(添加填充)

函数可以跨多个列搜索多个字符串并创建二进制输出变量

在R中,我如何使用滑动窗口计算位置,然后进行过滤?

R如何计算现有行的总和以添加新的数据行

扩展R中包含列表的数据框

当每个变量值只能 Select 一次时,如何从数据框中 Select 两个变量的组合?

有没有办法一次粘贴所有列

在点图上绘制置信度或预测区间ggplot2

如何在反曲线图中更改X标签

如何在条形图中的x和填充变量中包含多个响应变量?

R dplyr::带有名称注入(LHS of:=)的函数,稍后在:=的RHS上引用