Conditionally apply the piping pitch depending on the external value

Given the dplyr workflow:

require(dplyr) mtcars %>% tibble::rownames_to_column(var = "model") %>% filter(grepl(x = model, pattern = "Merc")) %>% group_by(am) %>% summarise(meanMPG = mean(mpg)) 

I am interested in conditionally applying filter depending on the value of applyFilter .

Decision

For applyFilter <- 1 rows are filtered using the string "Merc" , without a filter, all rows are returned.

 applyFilter <- 1 mtcars %>% tibble::rownames_to_column(var = "model") %>% filter(model %in% if (applyFilter) { rownames(mtcars)[grepl(x = rownames(mtcars), pattern = "Merc")] } else { rownames(mtcars) }) %>% group_by(am) %>% summarise(meanMPG = mean(mpg)) 

Problem

The proposed solution is inefficient, as the ifelse call is always evaluated; a more desirable approach would only evaluate the filter step for applyFilter <- 1 .

Attempt

An ineffective working solution would look like this:

 mtcars %>% tibble::rownames_to_column(var = "model") %>% # Only apply filter step if condition is met if (applyFilter) { filter(grepl(x = model, pattern = "Merc")) } %>% # Continue group_by(am) %>% summarise(meanMPG = mean(mpg)) 

Naturally, the above syntax is incorrect. This is just an illustration of what an ideal workflow should look like.


Desired Answer

  • I am not interested in creating an intermediate object; The workflow should resemble:

     startingObject %>% ... conditional filter ... final object 
  • Ideally, I would like to find a solution in which I can control whether the filter call is executed or not

+5
source share
1 answer

How about this approach:

 mtcars %>% tibble::rownames_to_column(var = "model") %>% filter(if(applyfilter== 1) grepl(x = model, pattern = "Merc") else TRUE) %>% group_by(am) %>% summarise(meanMPG = mean(mpg)) 

This means that grepl is evaluated only if applyfilter is 1, otherwise filter just processes a TRUE .


Or another option is to use {} :

 mtcars %>% tibble::rownames_to_column(var = "model") %>% {if(applyfilter == 1) filter(., grepl(x = model, pattern = "Merc")) else .} %>% group_by(am) %>% summarise(meanMPG = mean(mpg)) 

Obviously, there is another possible approach in which you simply break the pipe, conditionally make a filter, and then continue to work (I know that the OP did not ask for this, I just want to give another example to other readers)

 mtcars %<>% tibble::rownames_to_column(var = "model") if(applyfilter == 1) mtcars %<>% filter(grepl(x = model, pattern = "Merc")) mtcars %>% group_by(am) %>% summarise(meanMPG = mean(mpg)) 
+7
source

All Articles