строка фильтра, когда может быть затронуто несколько столбцов - PullRequest
2 голосов
/ 18 июня 2020

У меня есть эти данные:

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

Спасибо вам!

Ответы [ 3 ]

4 голосов
/ 18 июня 2020

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, ]
2 голосов
/ 18 июня 2020

Здесь всего два цента: это еще одно возможное решение, которое следует указаниям в документации 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 
1 голос
/ 18 июня 2020

Есть, конечно, старомодное незамысловатое, но многословное решение простого выражения всех «или».

mydf %>% filter(param1 == "R78" | param2 == "R78" | param3 == "R78" | param4 == "R78" )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...