ggcharts
ggcharts copied to clipboard
Standard evaluation functions
All functions currently use non-standard evaluation which is great for interactive use but IMO clumsy to program with. Having functions that accepts strings as arguments could come in very handy in {shiny}
apps.
Hi, Thomas,
Are you talking about making the kind of syntax below works?
line_chart(data = revenue_wide, x = "year", y = c("Roche", "Pfizer", "Novartis", "Bayer"))
If that is the case I can help.
Yes, that's exactly what I had in mind. {dplyr} used to have functions that accept strings rather than symbols, i.e. mutate_()
rather than mutate()
. This is much easier to program with if you know that the inputs are strings.
Nice!
So, what do you think it is a better approach?
I read this about NSE and SE, and find out that Hadley Wickham suggests creating one function to SE and another to NSE like you said, so it would be functions like bar_chart()
for NSE and bar_chart_()
for SE.
But, it is also possible to make an auto evaluation function, like:
auto_evaluate <- function(x) {
if(is.character(substitute(x))) {
x <- dplyr::sym(x)
} else {
x <- rlang::enquo(x)
}
return(x)
}
Which would replace in {ggcharts} functions:
x <- rlang::enquo(x)
y <- rlang::enquo(y)
facet <- rlang::enquo(facet)
for
x <- auto_evaluate(x)
y <- auto_evaluate(y)
facet <- auto_evaluate(facet)
Which one do you prefer? Do you know another approaches?
I really would like to contribute, but sometimes I'm not very confident about my knowledge in R and good practices.
Thanks!
I thought about something like the auto_evaluate
function you proposed as well. However, I don't think it works. Imagine a datasets containing a variable called var
and foo
. What happens in the following scenario?
var <- "foo"
auto_evaluate(var)
var
contains a string but is a symbol. I think this kind of ambiguity is the reason Hadley Wickham proposed to have to different functions: one with NSE and one with SE. Another approach is used quite frequently in base R: having a argument character.only
that controls how the argument is evaluated. One good example is library
:
pkg <- "dplyr"
library(pkg)
Error in library(pkg) : there is no package called ‘pkg’
library(pkg, character.only = TRUE)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
@nathaneastwood How would you handle this?
So I actually use a function in {poorman} for this type of thing: https://github.com/nathaneastwood/poorman/blob/master/R/utils.R#L31 It works ok, but I wouldn't rely on it.
By the way, is there no rlang solution to this? Since ggplot2 already imports rlang, I would be tempted to find a solution there, the dependency is already there.
By the way, have you considered the wrapr::let()
function? It's fantastic.
By the way, is there no rlang solution to this? Since ggplot2 already imports rlang, I would be tempted to find a solution there, the dependency is already there.
Yes, there are some possible solutions in rlang. I was considering create some function to convert SE to NSE input but it sounds pretty unsafe.
What do you think about functions like page()
and ls()
? Both try to automatically determine whether you want standard or non-standard evaluation.
I thought about it a lot and I am very convinced that it would be better to have a function for NSE and another for SE.
Another approach is used quite frequently in base R: having a argument
character.only
that controls how the argument is evaluated. One good example islibrary
:
I don’t think it’s a good idea to use an argument to change the behaviour of another argument because it makes function calls harder to understand. Don't you?
What do you think about having a function to SE and another to NSE? Make something like bar_plot()
and bar_plot_()
?
I think it's the safer approach.
I think having two separate functions, one with standard evaluation semantics and one with non-standard one is the way to go as it's completely transparent what is going on 👍