204 votes

Comparez deux data.frames pour trouver les lignes dans data.frame 1 qui ne sont pas présentes dans data.frame 2

J'ai les 2 data.frames suivantes :

a1 <- data.frame(a = 1:5, b=letters[1:5])
a2 <- data.frame(a = 1:3, b=letters[1:3])

Je veux trouver la ligne a1 qui n'a pas a2.

Existe-t-il une fonction intégrée pour ce type d'opération ?

(p.s : J'ai écrit une solution pour ça, je suis simplement curieux si quelqu'un a déjà fait un code plus élaboré)

Voici ma solution :

a1 <- data.frame(a = 1:5, b=letters[1:5])
a2 <- data.frame(a = 1:3, b=letters[1:3])

rows.in.a1.that.are.not.in.a2  <- function(a1,a2)
{
    a1.vec <- apply(a1, 1, paste, collapse = "")
    a2.vec <- apply(a2, 1, paste, collapse = "")
    a1.without.a2.rows <- a1[!a1.vec %in% a2.vec,]
    return(a1.without.a2.rows)
}
rows.in.a1.that.are.not.in.a2(a1,a2)

185voto

Rickard Points 304

sqldf fournit une bonne solution

a1 <- data.frame(a = 1:5, b=letters[1:5])
a2 <- data.frame(a = 1:3, b=letters[1:3])

require(sqldf)

a1NotIna2 <- sqldf('SELECT * FROM a1 EXCEPT SELECT * FROM a2')

Et les lignes qui sont dans les deux trames de données :

a1Ina2 <- sqldf('SELECT * FROM a1 INTERSECT SELECT * FROM a2')

La nouvelle version de dplyr a une fonction, anti_join, pour exactement ces types de comparaisons

require(dplyr) 
anti_join(a1,a2)

Et semi_join pour filtrer les lignes en a1 qui sont également en a2

semi_join(a1,a2)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X