1

I am trying to write a function that seems like it should be very simple but I am having problems with it. I want to write a function that takes in three arguements: a dataframe, x-axis variable and y-axis variable. Based on these, I want it to return a scatterplot in which the x-axis variable and y-axis variable can be changed. This is the very basic function I wrote:

scatter_plot <- function(dataframe, x_input, y_input) {
  plot <- ggplot(data = dataframe) +
    geom_point(mapping = aes(x = x_input, y = y_input),
    )
}

For reproducibility, consider the dataset midwest that is in the ggplot2 package. The code I wrote does not produce errors when I run it, but when I try to pass arguments into it, such as

scatter_plot(midwest, percollege, percpovertyknown)

the function returns

"Error in FUN(X[[i]], ...) : object 'percollege' not found"

It seems like it does not recognize the variables in the argument, but I have been playing around with the function for quite some time and I can't seem to figure it out. Can someone help me with how to fix this so my function works correctly?

Ric S
  • 9,073
  • 3
  • 25
  • 51
AMM
  • 61
  • 3
  • Does this answer your question? [Use of ggplot() within another function in R](https://stackoverflow.com/questions/5106782/use-of-ggplot-within-another-function-in-r) – 4rj4n May 29 '20 at 07:14
  • I often use `aes_string`, which also should be one of the answers in the thread I posted above. I'd think that can be nicely fitted in the code that you have now. – 4rj4n May 29 '20 at 07:16
  • 1
    @4rj4n apparently, `aes_string` is soft-deprecated now: https://ggplot2.tidyverse.org/reference/aes_.html – starja May 29 '20 at 07:18
  • Ah, thanks for that. I hadn't noticed that. So `aes_` is recommended there, which also can take strings, I see. – 4rj4n May 29 '20 at 07:22
  • 1
    @4rj4n no, none of the functions mentioned on this site. It is recommended to do tidy evaluation as you can see in the answers here or on https://tidyeval.tidyverse.org/dplyr.html – starja May 29 '20 at 07:25
  • Ah, I see now. I missed the life cycle header, mentioning all of it has been soft-deprecated. Well, time to change my code for newer analyses then. I earlier flagged this question as duplicate, which in principle is true, but the original question I refer to has not been updated to include answers that use tidy evaluation. – 4rj4n May 29 '20 at 12:03

2 Answers2

1

tidyverse uses non standard evaluation (NSE), which makes using its facilities in functions slightly more complicated than you expect. Here's a version of your function that works for me.

scatter_plot <- function(dataframe, x_input, y_input) {
  qX <- enquo(x_input)
  qY <- enquo(y_input)
  plot <- ggplot(data = dataframe) +
    geom_point(mapping = aes(x = !! qX, y = !! qY),
    )
  return(plot)
}

As you've assigned your plot to an object, I've added a return statement.

See here for more information on NSE.

Limey
  • 10,234
  • 2
  • 12
  • 32
0

Using !!rlang::ensym() in your function should work.

scatter_plot <- function(dataframe, x_input, y_input) {
  plot <- ggplot(data = dataframe) +
    geom_point(mapping = aes(x = !!rlang::ensym(x_input), y = !!rlang::ensym(y_input)))
  plot
}

Example

scatter_plot(midwest, percollege, percpovertyknown)

enter image description here

Ric S
  • 9,073
  • 3
  • 25
  • 51
  • 1
    I would use `aes(x = {{ x_input }}, y = {{ y_input }})`. – Lionel Henry May 29 '20 at 09:25
  • I didn't know about double curly brackets.. What is the difference between them and `ensym`? Do you have a reference link in which I can study their usage? – Ric S May 29 '20 at 09:34
  • 1
    There is https://ggplot2.tidyverse.org/articles/ggplot2-in-packages.html and https://dplyr.tidyverse.org/dev/articles/programming.html The main difference is that with curly brackets you can pass any expression, not just variable names. For instance `colour = `cut_number(x, 3)` will work properly if you tunnel the argument with `{{`. – Lionel Henry May 29 '20 at 09:51