left_join anti_join r join merge r-faq

left_join - anti_join r



Encontrar el complemento de un marco de datos(anti-join) (7)

Tengo dos marcos de datos (df y df1). df1 es un subconjunto de df. Quiero obtener un marco de datos que sea un complemento de df1 en df, es decir, devolver filas del primer conjunto de datos que no coinciden en el segundo. Por ejemplo, deja,

marco de datos df:

heads row1 row2 row3 row4 row5

trama de datos df1:

heads row3 row5

Entonces la salida deseada df2 es:

heads row1 row2 row4


Otra opción al crear una función negate_match_df manipulando el código de match_df del paquete plyr .

library(plyr) negate_match_df <- function (x, y, on = NULL) { if (is.null(on)) { on <- intersect(names(x), names(y)) message("Matching on: ", paste(on, collapse = ", ")) } keys <- join.keys(x, y, on) x[!keys$x %in% keys$y, , drop = FALSE] }

Datos

df <- read.table(text ="heads row1 row2 row3 row4 row5",header=TRUE) df1 <- read.table(text ="heads row3 row5",header=TRUE)

Salida

negate_match_df(df,df1)


Otra opción, usando la base R y la función setdiff :

df2 <- data.frame(heads = setdiff(df$heads, df1$heads))

setdiff funciona exactamente como te imaginas; tome ambos argumentos como conjuntos y elimine todos los elementos del segundo del primero.

Encuentro setdiff más legible ta %in% y prefiero no requerir bibliotecas adicionales cuando no las necesito, pero la respuesta que utiliza es en gran medida una cuestión de gusto personal.


Prueba anti_join de dplyr

library(dplyr) anti_join(df, df1, by=''heads'')


Pruebe el comando %in% y revertirlo con !

df[!df$heads %in% df1$heads,]


Respuesta tardía, pero para otra opción, podemos intentar hacer una combinación anti SQL formal, usando el paquete sqldf :

library(sqldf) sql <- "SELECT t1.heads FROM df t1 LEFT JOIN df1 t2 ON t1.heads = t2.heads WHERE t2.heads IS NULL" df2 <- sqldf(sql)

El paquete sqldf puede ser útil para aquellos problemas que se redactan fácilmente utilizando la lógica SQL, pero tal vez se formulan con menos facilidad utilizando la base R u otro paquete R.


También podría hacer algún tipo de anti combinación con data.table s binary join

library(data.table) setkey(setDT(df), heads)[!df1] # heads # 1: row1 # 2: row2 # 3: row4

EDITAR: a partir de data.table v1.9.6 + podemos unir data.tables sin configurar las teclas mientras se usa on

setDT(df)[!df1, on = "heads"]

EDIT2: se introdujo data.table v1.9.8 + fsetdiff que es básicamente una variación de la solución anterior, justo sobre todos los nombres de columna de x data.table, por ejemplo x[!y, on = names(x)] . Si all configurado en FALSE (el comportamiento predeterminado), solo se devolverán las filas únicas en x . Para el caso de solo una columna en cada tabla de datos, lo siguiente será equivalente a las soluciones anteriores

fsetdiff(df, df1, all = TRUE)


dplyr también tiene setdiff() que te dará el

setdiff(bigFrame, smallFrame) le proporciona los registros adicionales en la primera tabla.

entonces, para el ejemplo del OP, el código leería setdiff(df, df1)

dplyr tiene una gran funcionalidad: para obtener una guía rápida y fácil, consulte here.