J'ai les données suivantes:
Error: Problem with `filter()` input `..1`. x Input `..1$name1` must be a logical vector, not a character. i Input `..1` is `across(everything())`.
data %>% filter(across(everything()), !str.detect("John"))
Je souhaite filtrer toutes les lignes contenant la chaîne "John" sur toutes les colonnes (le nombre de colonnes peut être supérieur à 3).
J'essaye ce qui suit
> data name1 name2 name3 1 John Smith A V John Donovan 2 A A John Smith A R 3 A B A D John Donovan 4 A C A R A L 5 John Donovan A O A V 6 A F John Smith A Q 7 A D A M A T 8 A F A V A N 9 A D A L A L 10 A C A Q A X
Cependant cela ne fonctionne pas et cela produit:
data <- data.frame(name1 =c("John Smith", "A A", "A B", "A C", "John Donovan", "A F", "A D", "A F", "A D", "A C"), name2 = c("A V", "John Smith", "A D", "A R", "A O", "John Smith", "A M", "A V", "A L", "A Q"), name3 = c("John Donovan", "A R", "John Donovan", "A L", "A V", "A Q", "A T", "A N", "A L", "A X"))
Avez-vous une idée, en particulier celle qui utilise la fonction across.
3 Réponses :
filter prend un vecteur logique, donc lors de l'utilisation de across, vous devez passer la fonction à l'appel across pour appliquer cette fonction à toutes les colonnes sélectionnées:
df %>% filter(print(across(everything(), ~ str_detect(., "John")))) # A tibble: 10 x 3 V1 V2 V3 <lgl> <lgl> <lgl> 1 TRUE FALSE TRUE 2 FALSE TRUE FALSE 3 FALSE FALSE TRUE 4 FALSE FALSE FALSE 5 TRUE FALSE FALSE 6 FALSE TRUE FALSE 7 FALSE FALSE FALSE 8 FALSE FALSE FALSE 9 FALSE FALSE FALSE 10 FALSE FALSE FALSE [1] V1 V2 V3 <0 rows> (or 0-length row.names)
df %>% filter(print(across(everything(), ~ !str_detect(., "John")))) # A tibble: 10 x 3 V1 V2 V3 <lgl> <lgl> <lgl> 1 FALSE TRUE FALSE 2 TRUE FALSE TRUE 3 TRUE TRUE FALSE 4 TRUE TRUE TRUE 5 FALSE TRUE TRUE 6 TRUE FALSE TRUE 7 TRUE TRUE TRUE 8 TRUE TRUE TRUE 9 TRUE TRUE TRUE 10 TRUE TRUE TRUE V1 V2 V3 1 A C A R A L 2 A D A M A T 3 A F A V A N 4 A D A L A L 5 A C A Q A X
en utilisant la solution proposée dans le commentaire de @ekoam :
V1 V2 V3 1 John Smith A V John Donovan 2 A A John Smith A R 3 A B A D John Donovan 4 John Donovan A O A V 5 A F John Smith A Q
df %>% filter(rowSums(across(everything(), ~ str_detect(., "John"))) > 0)
Juste pour rendre l'image un peu plus claire:
V1 V2 V3 1 A C A R A L 2 A D A M A T 3 A F A V A N 4 A D A L A L 5 A C A Q A X
Notez que le filtre est &
(et) ing les booléens par ligne, c'est-à-dire que seules les lignes avec toutes les valeurs TRUE
seront sélectionnées, celles qui ont au moins un FALSE
ne le seront pas. Jetons maintenant un œil au code que vous avez fourni dans votre commentaire:
df %>% filter(across(everything(), ~ !str_detect(., "John")))
Toutes les lignes ont au moins un FALSE
, donc aucune ligne n'est sélectionnée.
Que faire si je veux trouver les lignes qui contiennent la chaîne John. Cela ne fonctionne pas: df%>% filter (across (tout (), ~ str_detect (., "John"))) Savez-vous pourquoi?
Pour filtrer toute colonne contenant "John", effectuez ce data %>% filter(rowSums(across(everything(), ~str_detect(., "John"))) > 0)
. @senad
@senad votre code vérifie essentiellement si toutes les colonnes contiennent John
. Le commentaire de @ ekoam est correct car il vérifie si au moins une colonne contient John
Voici quelques approches de base R.
En utilisant sapply
:
df[!Reduce(`|`, lapply(df, grepl, pattern = 'John')), ]
Avec lapply
:
df[rowSums(sapply(df, grepl, pattern = 'John')) == 0, ] # name1 name2 name3 #4 A C A R A L #7 A D A M A T #8 A F A V A N #9 A D A L A L #10 A C A Q A X
Merci Ronak. avez-vous une idée du commentaire sur la solution d'Abdessabour?
Vous pouvez utiliser df[rowSums(sapply(df, grepl, pattern = 'John')) > 0, ]
Nous pouvons également le faire de manière vectorisée
# name1 name2 name3 #4 A C A R A L #7 A D A M A T #8 A F A V A N #9 A D A L A L #10 A C A Q A X
-production
data[!rowSums(`dim<-`(grepl('John', as.matrix(data)), dim(data))),]