Using if_else or case_when to conditionally filter a dataframe in two different ways

Viewed 71

Minimal example - I have 9 responses from 3 subjects to a questionnaire with two questions:

set.seed(1)
df <- data.frame(ID = c(rep("A", 2), rep("B", 3), rep("C", 4)),
                 Q1 = sample(0:5, 9, replace=T),
                 Q2 = sample(1:7, 9, replace=T),
                 Days_Used = c(rep(10, 2), rep(5, 3), rep(4, 4))
)

Think of Days_Used as End_Date - Start_Date. I would like to filter the dataframe in one of two ways - by Days_Used or the number of times the questionnaire is filled (i.e. by the number of rows associated with a subject), depending on whether the variable FILTER_BY_DAYS_USED is TRUE or FALSE. I tried the following:

FILTER_BY_DAYS_USED <- TRUE
df %>% 
  group_by(ID) %>%
  if_else(FILTER_BY_DAYS_USED,
          filter(Days_Used >= 5),
          filter(n() >= 3))

but get an error message when I execute it

Error: `condition` must be a logical vector, not a grouped_df/tbl_df/tbl/data.frame` object.

I would like to obtain the following output:

  1. When FILTER_BY_DAYS_USED is TRUE: the first 5 rows corresponding to subjects A and B

  2. When FILTER_BY_DAYS_USED is FALSE: the last 7 rows corresponding to subjects B and C

What is the correct syntax for my conditional filter?

Many thanks in advance

Thomas Philips

1 Answers

You were in the right direction. Try using if/else since this is a scalar comparison.

library(dplyr)

FILTER_BY_DAYS_USED <- TRUE

df %>% 
  group_by(ID) %>%
  filter(if(FILTER_BY_DAYS_USED) Days_Used >= 5 else n() >= 3) %>%
  ungroup

#   ID       Q1    Q2 Days_Used
#  <chr> <int> <int>     <dbl>
#1 A         0     3        10
#2 A         3     1        10
#3 B         0     5         5
#4 B         1     5         5
#5 B         4     2         5
Related