在dplyr中使用filter,条件是R中的if语句

Can*_*ice 6 r dplyr

让我分享一下我正在尝试做的事情的一个例子,因为标题可能不像我希望的那样清晰.这没有可重现的代码,但我可以添加一个可重现的示例,如果这将有所帮助:

library(dplyr)
if(this_team != "") {
  newdf <- mydf %>%    
      filter(team == this_team) %>%
      mutate(totalrows = nrow(.)) %>%
      group_by(x1, y1) %>%
      summarize(dosomestuff)
} else {
  newdf <- mydf %>%    
      filter(firstname == this_name & lastname == that_name) %>%
      mutate(totalrows = nrow(.)) %>%
      group_by(x1, y1) %>%
      summarize(dosomestuff)
}
Run Code Online (Sandbox Code Playgroud)

我在R中创建一个函数,对mydf数据帧进行一些数据操作.如果我将值传递给函数的team_name参数,那么我想使用'team'列过滤数据帧.如果我没有将值传递给team_name参数,那么它默认为"",而是传递this_name和that_name的值,它们对应于mydf中的列'firstname'和'lastname'.

有没有更好的方法来做到这一点,而不是必须在两个单独的if else语句中再次创建整个dplyr管道?我的实际代码管道长度超过4行,因此必须重现这样的代码是非常令人沮丧的.

luk*_*keA 19

你可以做到

library(dplyr)
y <- ""
data.frame(x = 1:5) %>% 
  {if (y=="") filter(., x>3) else filter(., x<3)} %>% 
  tail(1)
Run Code Online (Sandbox Code Playgroud)

要么

data.frame(x = 1:5) %>% 
 filter(if (y=="") x>3 else x<3) %>%  
  tail(1)
Run Code Online (Sandbox Code Playgroud)

甚至将管道存放在静脉中

mypipe <- . %>% tail(1) %>% print
data.frame(x = 1:5) %>% mypipe
Run Code Online (Sandbox Code Playgroud)

  • 很好的解决方案。只有一个问题:为什么即使在既没有输入 if 也没有输入 else 子句的情况下这仍然有效?然后 dplyr 通过双管道运算符但不会抱怨 - 但为什么? (2认同)
  • 值得注意的是,filter语句中的if语句需要有else子句,否则会出错 (2认同)

R m*_*tey 14

基于 lukeA 的评论,您还可以使用case_when()

library(dplyr)
y <- ""
data.frame(x = 1:5) %>% 
  filter(case_when(y=="" ~ x > 3, #When y == "", x > 3
                   T ~ x<3) #Otherwise, x < 3
         ) %>% 
  tail(1)
Run Code Online (Sandbox Code Playgroud)

如果您有两个以上的条件需要评估,这会更好。


小智 6

看看下面的代码是否有效,我们if-elsefilter语句中插入条件。这是有道理的,因为后面的语句接受逻辑语句作为其输入——我们只是使用前面的语句来控制输入的值。

library(dplyr)

newdf <- mydf %>%    
  filter(
    if (this_team != "") {
      team == this_team
    } else {
      firstname == this_name & lastname == that_name
    }
  ) %>%
  mutate(totalrows = nrow(.)) %>%
  group_by(x1, y1) %>%
  summarize(dosomestuff)
Run Code Online (Sandbox Code Playgroud)

  • 我观察到,在您只想返回未经过滤的数据的情况下,您可以像这样设置 if else `data %&gt;% filter( if (this_team != "") { team == this_team } else { team = = team })` 当 `else` 表示用户没有选择任何过滤条件并且不想进行过滤时,这很有用。 (5认同)