Skip to content

aes() should accept !!! at its first and second argument #2675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
yutannihilation opened this issue May 30, 2018 · 7 comments · Fixed by #4802
Closed

aes() should accept !!! at its first and second argument #2675

yutannihilation opened this issue May 30, 2018 · 7 comments · Fixed by #4802
Labels
feature a feature request or enhancement

Comments

@yutannihilation
Copy link
Member

I feel this is a bit counter-intuitive. Is it possible to introduce some tweak to enable this?

library(ggplot2)

q <- quos(colour = Species)
aes(!!!q)
#> Error: Can't use `!!!` at top level

aes(x, y, !!!q)
#> Aesthetic mapping: 
#> * `x`      -> `x`
#> * `y`      -> `y`
#> * `colour` -> `Species`

Created on 2018-05-31 by the reprex package (v0.2.0).

@hadley
Copy link
Member

hadley commented May 30, 2018

@lionel- can you please take a look/think about this? (The problem is that aes() has x and y arguments)

@hadley
Copy link
Member

hadley commented Jul 22, 2018

Until we figure this out, there's a work around:

aes(,, !!!q)

@yutannihilation
Copy link
Member Author

This isn't very clean, but I think we can introduce some tweak like this.

library(rlang)

aes <- function (x, y, ...) {
  x_expr <- quo_get_expr(enquo0(x))
  
  if (startsWith(expr_deparse(x_expr), "!!!")) {
    expr <- expr(quos(!!x_expr))
    exprs <- eval(expr, caller_env())
  } else {
    exprs <- enquos(x = x, y = y, ..., .ignore_empty = "all")
  }
  
  aes <- ggplot2:::new_aes(exprs, env = parent.frame())
  ggplot2:::rename_aes(aes)
}

aes(x, y, colour = Species)
#> Aesthetic mapping: 
#> * `x`      -> `x`
#> * `y`      -> `y`
#> * `colour` -> `Species`

q <- quos(colour = Species)
aes(!!!q)
#> Aesthetic mapping: 
#> * `colour` -> `Species`

Created on 2022-04-14 by the reprex package (v2.0.1)

@teunbrand
Copy link
Collaborator

teunbrand commented Apr 15, 2022

I'm not fluent in {rlang}, but I can improvise on a theme, in this case Yutannihilation's code above.
I've taken the idea above and made it slightly more flexible in terms of where the !!!q can be placed in aes().

library(rlang)

try_inject <- function(var, name, exprs, env = caller_env()) {

  expr <- quo_get_expr(var)
  if (is_missing(expr)) {
    return(exprs)
  }
  
  if (startsWith(expr_deparse(expr), "!!!")) {
    expr <- expr(quos(!!expr))
    expr <- eval(expr, env)
  } else {
    expr <- enquos(var, .ignore_empty = "all")
    names(expr) <- name
  }
  c(exprs, expr)
}

aes <- function(x, y, ...) {
  
  exprs <- enquos(..., .ignore_empty = "all")
  exprs <- try_inject(enquo0(x), "x", exprs)
  exprs <- try_inject(enquo0(y), "y", exprs)
  
  aes <- ggplot2:::new_aes(exprs, env = parent.frame())
  ggplot2:::rename_aes(aes)
  
}

q <- quos(colour = Species)

# New cases that now work
aes(x = Sepal.Width, !!!q)
#> Aesthetic mapping: 
#> * `x`      -> `Sepal.Width`
#> * `colour` -> `Species`
aes(y = Petal.Width, !!!q)
#> Aesthetic mapping: 
#> * `colour` -> `Species`
#> * `y`      -> `Petal.Width`

# These already worked with Yutannilation's code
aes(x = Sepal.Width, y = Petal.Width, !!!q)
#> Aesthetic mapping: 
#> * `colour` -> `Species`
#> * `x`      -> `Sepal.Width`
#> * `y`      -> `Petal.Width`
aes(!!!q)
#> Aesthetic mapping: 
#> * `colour` -> `Species`

Created on 2022-04-15 by the reprex package (v2.0.1)

@yutannihilation
Copy link
Member Author

Cool. You are already better at using rlang than I!

@lionel-
Copy link
Member

lionel- commented Apr 19, 2022

Thanks @yutannihilation and @teunbrand! I've sent #4802 based on your implementations.

@yutannihilation
Copy link
Member Author

Thanks!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature a feature request or enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants