2

我有这个数据:

# 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 

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

我尝试:

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:/

多亏了你!

4

3 回答 3

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, ]
于 2020-06-18T11:45:16.893 回答
2

只是我的两分钱:这是另一种可能的解决方案,在谈论该功能时遵循 dplyr文档中的指示。filter它说:

以前,与和助手filter()配对。现在,相当于,并且没有直接替代. 但是,您可以自己制作一个简单的助手。all_vars()any_vars()across()all_vars()any_vars()

在这里,我创建了一个辅助函数rowAny,它根据条件x == "R78"是否满足返回一个逻辑向量,然后我将它应用到由across.

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 
于 2020-06-18T13:43:42.263 回答
1

当然,还有一种老式的简单但冗长的解决方案,即只表达所有的“或”。

mydf %>% filter(param1 == "R78" | param2 == "R78" | param3 == "R78" | param4 == "R78" )
于 2020-06-18T11:53:53.923 回答