web-dev-qa-db-fra.com

Comment sélectionner des lignes selon deux critères dans data.table in R

Disons que j'ai une table de données et que je veux sélectionner toutes les lignes où la variable x a une valeur de b. C'est facile

library(data.table)
DT <- data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9)
setkey(DT,x)               # set a 1-column key
DT["b"]

Soit dit en passant, il semble que l'on doit définir une clé, si la clé n'est pas définie sur x, cela ne fonctionne pas. Au fait, que se passerait-il si je définissais deux colonnes comme clés?

Quoi qu'il en soit, en avançant, disons que je veux sélectionner toutes les lignes où la variable x était a ou b

DT["b"|"a"]

ne marche pas

Mais les œuvres suivantes

DT[x=="a"|x=="b"]

Mais cela utilise un balayage vectoriel sur les trames de données. Il n'utilise pas la recherche binaire. Je suppose que pour les petits ensembles de données, cela n'aura pas d'importance.

Est-ce ce que je dois faire ou suis-je ignorant de la syntaxe data.table?

Et encore une chose. Existe-t-il des exemples de procédures de sélection (ou sous-ensemble) de variables booléennes plus complexes avec data.table?

Je sais que je pourrais toujours revenir à l'utilisation de la fonction subset () car un data.table se comportera comme un data.frame s'il le faut.

27
Farrel

Voici une façon qui ne m'est venue à l'esprit qu'après avoir posé la question et ça marche mais je ne sais pas comment ça se passe dans les benchmarks. Je ne suis pas actuellement sur un ordinateur avec un R. installé. Je suppose que je devrais utiliser une instance cloud. Quoi qu'il en soit, j'aime la syntaxe

DT[c("a","b")]
15
Farrel

En utilisant le %in% L'opérateur semble donner un facteur de 2 bosse de performance. Considérer:

library(data.table)
library(rbenchmark)
DT <- data.table(x=sample(letters, 1e6, TRUE), y=rnorm(1e6), v=runif(1e6))
setkey(DT,x)               # set a 1-column key
DT["b"]
f1 <- function() DT[x %in% letters[1:2]]
f2 <- function() DT[x=="a"| x == "b"]

> benchmark(f1(),f2())
  test replications elapsed relative user.self sys.self user.child sys.child
1 f1()          100    8.40 1.000000      7.58     0.81         NA        NA
2 f2()          100   17.11 2.036905     15.54     1.56         NA        NA

> all.equal(f1(), f2())
[1] TRUE

EDIT: Ajout de l'option de Farrel

Notez que ceci est sur un ordinateur différent, mais les bosses relatives sont les mêmes.

f3 <- function() DT[c("a", "b")]

  test replications elapsed  relative user.self sys.self user.child sys.child
1 f1()          100  11.281  7.121843     9.745    1.323          0         0
2 f2()          100  23.106 14.587121    20.824    2.224          0         0
3 f3()          100   1.584  1.000000     1.042    0.541          0         0
14
Chase