可以考虑多列时过滤行

时间:2020-06-18 11:42:02

标签: r filter dplyr across

我有以下数据:

# A tibble: 20 x 6
      ID style param1 param2 param3 param4
   <dbl> <chr> <chr>  <chr>  <chr>  <chr> 
 1     1 ar    R78    NA     NA     NA    
 2     2 bg    NA     NA     NA     NA    
 3     3 bh    NA     NA     NA     NA    
 4     4 ar    NA     R78    NA     NA    
 5     5 bg    NA     NA     NA     NA    
 6     6 bh    NA     NA     NA     NA    
 7     7 ar    R78    NA     NA     NA    
 8     8 bg    NA     NA     R78    NA    
 9     9 bh    NA     NA     NA     NA    
10    10 ar    NA     R78    NA     NA    
11    11 bg    NA     NA     NA     NA    
12    12 bh    NA     NA     R78    NA    
13    13 ar    NA     NA     NA     NA    
14    14 bg    R78    NA     NA     NA    
15    15 bh    NA     NA     NA     NA    
16    16 ar    NA     NA     NA     NA    
17    17 bg    NA     NA     NA     NA    
18    18 bh    R78    NA     NA     NA    
19    19 ar    NA     NA     NA     R78   
20    20 bg    NA     NA     NA     NA 

当R78在列param1,param2,param3或param4中时,我想使用dplyr::filter选择行

我尝试:

data %>%
  filter(across(param1:param4) == "R78")

返回我的

# A tibble: 4 x 6
     ID style param1 param2 param3 param4
  <dbl> <chr> <chr>  <chr>  <chr>  <chr> 
1     1 ar    R78    NA     NA     NA    
2     7 ar    R78    NA     NA     NA    
3    14 bg    R78    NA     NA     NA    
4    18 bh    R78    NA     NA     NA  

这与我做data %>% filter(param1 == "R78")

时相同

...

也许我滥用了“跨”功能。我尝试使用倍数“ |”但从不工作:/

我对代码的期望是它必须使我回到第1、4、7、10、12、14行的位置;仅18和19:/

向您致意!

3 个答案:

答案 0 :(得分:4)

across按列工作。在这种情况下,我认为最好使用filter_at

library(dplyr)
df %>% filter_at(vars(param1:param4), any_vars(. == 'R78'))

#   ID style param1 param2 param3 param4
#1   1    ar    R78   <NA>   <NA>   <NA>
#4   4    ar   <NA>    R78   <NA>   <NA>
#7   7    ar    R78   <NA>   <NA>   <NA>
#8   8    bg   <NA>   <NA>    R78   <NA>
#10 10    ar   <NA>    R78   <NA>   <NA>
#12 12    bh   <NA>   <NA>    R78   <NA>
#14 14    bg    R78   <NA>   <NA>   <NA>
#18 18    bh    R78   <NA>   <NA>   <NA>
#19 19    ar   <NA>   <NA>   <NA>    R78

使across起作用的一种技巧是使用Reduce

df %>% filter(Reduce(`|`, across(param1:param4, ~. == 'R78')))

在基数R中,您可以使用rowSums

cols <- paste0('param', 1:4)
df[rowSums(df[cols] == 'R78', na.rm = TRUE) > 0, ]

答案 1 :(得分:2)

这里只有两美分:这是另一种可能的解决方案,当谈论filter函数时,遵循dplyr的documentation上的指示。它说:

以前,filter()all_vars()any_vars()助手配对。现在,across()等效于all_vars(),并且无法直接替换any_vars()。但是,您可以自己做一个简单的助手。

在这里,我创建辅助函数rowAny,该函数将返回一个逻辑向量,根据该逻辑向量满足或不满足条件x == "R78",然后将其应用于across指定的变量。 / p>

rowAny <- function(x) {rowSums(x == "R78", na.rm = TRUE) > 0}
df %>% filter(rowAny(across(param1:param4)))

# A tibble: 9 x 6
#      ID style param1 param2 param3 param4
#   <int> <chr> <chr>  <chr>  <chr>  <chr> 
# 1     1 ar    R78    NA     NA     NA    
# 2     4 ar    NA     R78    NA     NA    
# 3     7 ar    R78    NA     NA     NA    
# 4     8 bg    NA     NA     R78    NA    
# 5    10 ar    NA     R78    NA     NA    
# 6    12 bh    NA     NA     R78    NA    
# 7    14 bg    R78    NA     NA     NA    
# 8    18 bh    R78    NA     NA     NA    
# 9    19 ar    NA     NA     NA     R78 

答案 2 :(得分:1)

当然有只表达所有“或”的老式简单但罗word的解决方案。

mydf %>% filter(param1 == "R78" | param2 == "R78" | param3 == "R78" | param4 == "R78" )
相关问题