1

Just for clarification, not intended to reopen, as I will start a follow-up question:

  • This not a question about using an ifelse in dplyr.
  • This is a question about passing by an argument in a custom function. This is important for certain (not mentioned) reasons!

Original question:

I have this example with the mtcars dataset:

  • Where basically the dataframe is filtered and then plotted.
  • I wonder if it is possible to make the plot of the unfiltered data by this function ignoring the filtering variable z:
# create a custom function
my_function <- function(df, x, y, z) {
  df %>% 
    filter(am == z) %>% 
  ggplot(aes(x = {{x}}, y={{y}}))+
    geom_col()
}

apply function with filter am==0 <- WORKS

my_function(mtcars, cyl, mpg, 0)

apply function with filter am==1 <- WORKS

my_function(mtcars, cyl, mpg, 1) 

would like to ignore the filter argument to get plot of all data <- WORKS NOT

my_function(mtcars, cyl, mpg)

Error in `filter()`:
  ! Problem while computing `..1 = am == z`.
Caused by error:
  ! argument "z" is missing, with no default
TarJae
  • 72,363
  • 6
  • 19
  • 66
  • 1
    You could check if the argument was supplied and conditinally perform the filter: `my_function <- function(df, x, y, z) {hasz <- !missing(z); df %>% {if (hasz) filter(., am==z) else .} %>% ggplot(aes(x = {{x}}, y={{y}})) +geom_col()}` – MrFlick Jun 17 '22 at 20:05
  • @MrFlick. It seems that you are quite experienced here. This question is closed. But I don't understand why. This not a question about using an ifelse in dplyr. This is a question about passing by an argument in a custom function. As you can see that I have already a little experience and I am following a certain quest. In this case my ultimate goal is to solve the last line of my function: `anim_save(paste0("images/survival_", z, ".gif"))`. And if z = NULL it starts to save all other ever filtered images. But the first was to understand how to bypass an argument. Could you clarify. Many thnx – TarJae Jun 17 '22 at 20:10
  • 1
    You framed the question as you were interesting in conditionally filtering data only under certain circumstances. I was unable to guess what your true intention was. But there are plenty of existing questions about testing if a parameter has passed. I can add a duplicate for that if you like as well. – MrFlick Jun 17 '22 at 20:12
  • @MrFlick. Now after going through all again. I think you are right. Thanks for clarifying! – TarJae Jun 17 '22 at 20:37

1 Answers1

3

It is about working with the default.

I'd suggest having a default z = NULL, then your function would look like this.\

# create a custom function
my_function <- function(df, x, y, z = NULL) {
  
  if (!is.null(z)) {
   df <-  df %>% 
      filter(am == z)
  }
  
df %>% 
    ggplot(aes(x = {{ x }}, y = {{ y }})) +
    geom_col()
}

my_function(mtcars, cyl, mpg, 0)

my_function(mtcars, cyl, mpg, 1) 
my_function(mtcars, cyl, mpg)
olivroy
  • 548
  • 3
  • 13
  • 1
    You can also use `if (missing(z))` (and don't need a default setting), but I prefer your solution. – Ben Bolker Jun 17 '22 at 20:00
  • Yes, it looks more obvious that `z` is different variable type than x and y. – olivroy Jun 17 '22 at 20:05
  • @olivroy. Thanks this solved also my main issue, i.e how to save without the filter argument! – TarJae Jun 17 '22 at 20:37
  • @olivroy, also easier if the function is being called indirectly (it's easy to force a parameter to be `NULL`, very hard to force it to be "missing") – Ben Bolker Jun 17 '22 at 20:51