web-dev-qa-db-fra.com

Filtrer plusieurs valeurs sur une colonne de chaîne dans dplyr

J'ai un data.frame avec des données de caractères dans l'une des colonnes. Je voudrais filtrer plusieurs options dans le data.frame de la même colonne. Y at-il un moyen facile de faire cela qui me manque?

Exemple:data.frame name = dat

days      name
88        Lynn
11          Tom
2           Chris
5           Lisa
22        Kyla
1          Tom
222      Lynn
2         Lynn

J'aimerais filtrer Tom et Lynn par exemple.
Quand je fais:

target <- c("Tom", "Lynn")
filt <- filter(dat, name == target)

Je reçois cette erreur:

longer object length is not a multiple of shorter object length
61
Tom O

Vous avez besoin de %in% au lieu de ==:

library(dplyr)
target <- c("Tom", "Lynn")
filter(dat, name %in% target)  # equivalently, dat %>% filter(name %in% target)

Produit

  days name
1   88 Lynn
2   11  Tom
3    1  Tom
4  222 Lynn
5    2 Lynn

Pour comprendre pourquoi, considérons ce qui se passe ici:

dat$name == target
# [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE

Fondamentalement, nous recyclons quatre fois le vecteur target length afin de faire correspondre la longueur de dat$name. En d'autres termes, nous faisons:

 Lynn == Tom
  Tom == Lynn
Chris == Tom
 Lisa == Lynn
 ... continue repeating Tom and Lynn until end of data frame

Dans ce cas, nous n'obtenons pas d'erreur, car je soupçonne que votre trame de données comporte en fait un nombre différent de lignes qui ne permettent pas le recyclage, mais l'échantillon que vous fournissez en contient (8 lignes). Si l'échantillon avait eu un nombre impair de lignes, j'aurais eu la même erreur que vous. Mais même lorsque le recyclage fonctionne, ce n’est clairement pas ce que vous voulez. En gros, l'instruction dat$name == target équivaut à dire:

return TRUE pour chaque valeur impaire égale à "Tom" ou chaque valeur paire égale à "Lynn".

Il se trouve que la dernière valeur de votre trame de données exemple est égale et égale à "Lynn", d'où celle TRUE ci-dessus.

Par contraste, dat$name %in% target dit:

pour chaque valeur dans dat$name, vérifiez qu'elle existe dans target.

Très différent. Voici le résultat:

[1]  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE

Notez que votre problème n'a rien à voir avec dplyr, juste à la mauvaise utilisation de ==.

165
BrodieG

Ceci peut être réalisé en utilisant le package dplyr, disponible dans CRAN. Le moyen simple d'y parvenir:

  1. Installez le paquet dplyr.

  2. library(dplyr) df<- select(filter(dat,name=='tom'| name=='Lynn',c('days','name))

Explication:

Donc, une fois que nous avons téléchargé dplyr, nous créons un nouveau bloc de données en utilisant deux fonctions différentes de ce paquet:

filtre: le premier argument est le cadre de données; le deuxième argument est la condition par laquelle nous voulons le sous-définir. Le résultat est l'ensemble du cadre de données avec uniquement les lignes que nous souhaitions. select: le premier argument est le cadre de données; le deuxième argument est le nom des colonnes que nous voulons en sélectionner. Nous n’avons pas besoin d’utiliser la fonction names () et nous n’avons même pas besoin de guillemets. Nous listons simplement les noms de colonnes sous forme d'objets.

9
AutomationNerd

Utilisation du package base:

df <- data.frame(days = c(88, 11, 2, 5, 22, 1, 222, 2), name = c("Lynn", "Tom", "Chris", "Lisa", "Kyla", "Tom", "Lynn", "Lynn"))

# Three lines
target <- c("Tom", "Lynn")
index <- df$name %in% target
df[index, ]

# One line
df[df$name %in% c("Tom", "Lynn"), ] 

Sortie:

  days name
1   88 Lynn
2   11  Tom
6    1  Tom
7  222 Lynn
8    2 Lynn

Utiliser sqldf:

library(sqldf)
# Two alternatives:
sqldf('SELECT *
      FROM df 
      WHERE name = "Tom" OR name = "Lynn"')
sqldf('SELECT *
      FROM df 
      WHERE name IN ("Tom", "Lynn")')
9
mpalanco