R语言 结合预定义的美学(ggplot2)

cgvd09ve  于 2024-01-03  发布在  其他
关注(0)|答案(2)|浏览(100)

我有一个函数可以选择接受预定义的美学(对于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将合并 * 不同的 * 美学结合起来,如

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


(The情节本身并不重要,重要的是它能起作用。)
x1c 0d1x的数据
如果我想在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(..)

xv8emn3q

xv8emn3q1#

你可以使用一些rlang魔法来操纵Map。简单地说,如果它是abent,我们就分配新的美学,否则我们创建一个新的调用组合两个表达式。

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()


x1c 0d1x的数据
创建于2023-12-22使用reprex v2.0.2

5gfr0r5j

5gfr0r5j2#

我希望这能给你一个如何解决这个问题的方向。这是矢量化的,这样所有重复的美学都会被结合起来:

merge_aes <- function(mappings, ...){
    a <- unlist(list(mappings, ...))
    nms <- names(a)
    names(a) <- NULL
    f <- quote(interaction)
    b <- names(which(table(nms) > 1))
    if(!length(b)) return(a)
    fn <- \(x)if(length(x)>1) as.call(c(f,x))   else x
    g <- unlist(tapply(sapply(a, rlang::quo_squash), nms, fn))
    eval(as.call(c(quote(aes), g)))
}

mapping <- aes(color = factor(cyl))
othermap1 <- aes(x = mpg, y = disp)
othermap2 <- aes(color = gear)

merge_aes(mapping, othermap1,
                    othermap2,
                    aes(group = vs),
                    aes(group = am),
                    aes(shape = factor(am)),
                    aes(shape = factor(vs)))
Aesthetic mapping: 
* `x`      -> `mpg`
* `y`      -> `disp`
* `colour` -> `interaction(factor(cyl), gear)`
* `group`  -> `interaction(vs, am)`
* `shape`  -> `interaction(factor(am), factor(vs))`

个字符


的数据

相关问题