правильный способ условной фильтрации в цепочке dplyr

#r #dplyr

#r #dplyr

Вопрос:

 library(tidyverse)
set.seed(041019)
  

Я определил простую функцию, которая добавляет 2 столбца вместе, например, в этом примере:

 # data    
dat <- data.frame("x" = sample(1:100, 10), "y" = sample(1:100, 10))

# define function
addXY <- function(dat) {
 datOut <- dat %>%
 mutate(z = x   y)
 return(datOut)
}

addXY(dat)

    x  y   z
1  80 30 110
2  28 16  44
3  11 61  72
4  37 24  61
5  29 44  73
6  62 33  95
7  94 50 144
8  59 59 118
9  88 39 127
10 65 78 143
  

Допустим, я хочу добавить двоичный аргумент к этой функции и использовать его для условной фильтрации в цепочке dplyr. Как бы я правильно это сделал. Я пробовал это, но это не работает:

 addXY <- function(dat, aboveFifty = TRUE) {
  datOut -> dat %>%
    if (!aboveFifty) {filter(x < 50)} else {filter(x <= 100)} %>%
    mutate(z = x   y)
    return(datOut)
}
addXY(dat, aboveFifty = FALSE)
  

Сбой с сообщением об ошибке:

 Error in if (.) !aboveFifty else { : 
  argument is not interpretable as logical
In addition: Warning message:
In if (.) !aboveFifty else { :
  the condition has length > 1 and only the first element will be used
  

Похоже, что он пытается фильтровать аргумент, а не данные, что, очевидно, не то, что я хочу.

Комментарии:

1. Опечатка, отредактировано сейчас.

2. В настоящее время неясно, куда / что dat передается по каналу. Вы можете обойти это, заключив весь оператор в фигурные скобки и используя точки filter() . Нравится dat %>% {if (!aboveFifty) {filter(., x < 50)} else {filter(., x <= 100)} }

3. хороший. Это работает. Спасибо

4. Поскольку у вас уже есть эта операция фильтрации в функции, вы можете добавить присвоение пороговой переменной, а затем выполнить фильтрацию на основе этого

Ответ №1:

Вы можете поместить if оператор в свой filter :

 addXY <- function(x, aboveFifty = T) x %>%
  filter(if (aboveFifty) x < 50 else x < 100) %>%
  mutate(z = x   y)

addXY(dat)

   x  y  z
1 28 16 44
2 11 61 72
3 37 24 61
4 29 44 73