1
votes

Comment sélectionner des lignes dans une data.table correspondant simultanément à deux conditions dans une autre data.table?

J'ai deux data.tables DT1 et DT2 , avec DT1 probablement plus grand et plus de colonnes que DT2 . Je souhaite sélectionner des lignes dans DT1 où deux colonnes de DT1 ont des correspondances exactes dans la même ligne de deux colonnes dans DT2 . Par exemple

DT1sub<-c()
for (i in 1:2)
  DT1sub<-rbind(DT1sub,DT1[x==DT2$f[i] & y==DT2$g[i]])
DT1sub

La sortie, DT1sub , que je recherche est

> DT1[x%in%DT2$f & y%in%DT2$g]
#    x y z
# 1: b 1 1
# 2: b 3 2
# 3: a 1 4
# 4: a 3 5

Mon problème est, lorsque j'essaie de sous-ensembles DT1 , j'obtiens également les lignes pour lesquelles une seule colonne correspond

   x y z
1: a 1 4
2: b 3 2

Je pourrais obtenir la sortie souhaitée, DT1sub , avec une boucle for maladroite comme

DT1 = data.table(x=rep(c("b","a","c"),each=3), y=c(1,3,6), z=1:9)
DT2 = data.table(f=c("a","b"), g=c(1,3))

mais je me demandais s'il y avait une version data.table plus intelligente de cela. C'est probablement simple, mais je n'ai pas pu le reconstituer à partir de example("data.table").


0 commentaires

3 Réponses :


4
votes

Recherchez-vous:

   x y z
1: a 1 4
2: b 3 2

Résultat:

library(data.table)

DT1sub <- DT1[DT2, on = .(x = f, y = g)]

Il s'agit essentiellement d'une jointure de filtrage - elle ne conserve que ces lignes dans x qui correspondent à tout ce qui se trouve dans f , et de même pour y et g.


2 commentaires

Exactement ce que je cherchais. Merci beaucoup!


Je vous en prie! Pensez à accepter la réponse si cela vous a aidé.



1
votes

Une autre idée est d'utiliser setkey.

library(data.table)

DT1 = data.table(x=rep(c("b","a","c"),each=3), y=c(1,3,6), z=1:9)
DT2 = data.table(f=c("a","b"), g=c(1,3))

setkey(DT1, x, y)
setkey(DT2, f, g)

DT1[DT2]
#    x y z
# 1: a 1 4
# 2: b 3 2


1 commentaires

Incroyable, merci beaucoup aussi! Tant de choses à apprendre avec data.table!



1
votes

Les réponses ci-dessus fonctionnent très bien mais je préfère toujours utiliser merge () pour cette tâche car ses arguments sont plus expressifs:

DT1sub <- merge(
  x = DT1, 
  y = DT2, 
  by.x = c('x', 'y'), by.y = c('f', 'g'), all.x = FALSE, all.y = FALSE)

Bien sûr, certains des les arguments sont redondants car ils sont définis par défaut, mais l'écrire de cette façon vous permet de vous rappeler si vous avez imposé une jointure interne / externe, etc.


1 commentaires

Merci, c'est une explication utile du code plus abrégé que donnent les deux autres réponses. Pour voir qu'ils fonctionnent tous comme des opérations de fusion, il est utile de redéfinir DT2 dans ma question avec une troisième colonne, qui sera ajoutée à DT1sub . Par exemple. DT2 = data.table (f = c ("a", "b"), g = c (1,3), k = c (1,2)) .