web-dev-qa-db-fra.com

Sélectionner des lignes dans un bloc de données en fonction des valeurs d'un vecteur

J'ai des données similaires à ceci:

dt <- structure(list(fct = structure(c(1L, 2L, 3L, 4L, 3L, 4L, 1L, 2L, 3L, 1L, 2L, 3L, 2L, 3L, 4L), .Label = c("a", "b", "c", "d"), class = "factor"), X = c(2L, 4L, 3L, 2L, 5L, 4L, 7L, 2L, 9L, 1L, 4L, 2L, 5L, 4L, 2L)), .Names = c("fct", "X"), class = "data.frame", row.names = c(NA, -15L))

Je souhaite sélectionner des lignes dans ce cadre de données en fonction des valeurs de la variable fct. Par exemple, si je souhaite sélectionner des lignes contenant "a" ou "c", je peux le faire:

dt[dt$fct == 'a' | dt$fct == 'c', ]

qui donne

1    a 2
3    c 3
5    c 5
7    a 7
9    c 9
10   a 1
12   c 2
14   c 4

comme prévu. Mais mes données réelles sont plus complexes et je souhaite réellement sélectionner des lignes en fonction des valeurs d'un vecteur tel que

vc <- c('a', 'c')

Alors j'ai essayé

dt[dt$fct == vc, ]

mais bien sûr ça ne marche pas. Je sais que je pourrais coder quelque chose pour parcourir le vecteur, extraire les lignes nécessaires et les ajouter à une nouvelle trame de données, mais j'espérais qu'il existait un moyen plus élégant.

Alors, comment puis-je filtrer/sous-définir mes données en fonction du contenu du vecteur vc?

56
Joe King

Jettes un coup d'oeil à ?"%in%".

dt[dt$fct %in% vc,]
   fct X
1    a 2
3    c 3
5    c 5
7    a 7
9    c 9
10   a 1
12   c 2
14   c 4

Vous pouvez aussi utiliser ?is.element:

dt[is.element(dt$fct, vc),]
102
johannes

Semblable à ce qui précède, utilisez filter de dplyr:

filter(df, fct %in% vc)
21
Andrew Haynes

Une autre option serait d'utiliser un data.table À clé:

library(data.table)
setDT(dt, key = 'fct')[J(vc)]  # or: setDT(dt, key = 'fct')[.(vc)]

qui se traduit par:

   fct X
1:   a 2
2:   a 7
3:   a 1
4:   c 3
5:   c 5
6:   c 9
7:   c 2
8:   c 4

Qu'est-ce que cela fait:

  • setDT(dt, key = 'fct') transforme le data.frame en un data.table (qui est une forme améliorée d'un data.frame) avec la colonne fct définie comme clé .
  • Ensuite, vous pouvez simplement créer un sous-ensemble avec le vecteur vc avec [J(vc)].

REMARQUE: lorsque la clé est une variable facteur/caractère, vous pouvez également utiliser setDT(dt, key = 'fct')[vc], mais cela ne fonctionnera pas si vc est un vecteur numérique. Lorsque vc est un vecteur numérique et qu'il n'est pas encapsulé dans J() ou .(), vc fonctionnera comme un index de ligne.

Une explication plus détaillée du concept de touches et du sous-ensemble se trouve dans la vignette Touches et Sous-ensemble de recherche binaire rapide .

Une alternative suggérée par @Frank dans les commentaires:

setDT(dt)[J(vc), on=.(fct)]

Lorsque vc contient des valeurs qui ne sont pas présentes dans dt, vous devez ajouter nomatch = 0:

setDT(dt, key = 'fct')[J(vc), nomatch = 0]

ou:

setDT(dt)[J(vc), on=.(fct), nomatch = 0]
8
Jaap