Encontrar el complemento de un dataframe (antiunión)

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

dataframe df:

heads row1 row2 row3 row4 row5 

dataframe df1:

 heads row3 row5 

Entonces, la salida deseada df2 es:

 heads row1 row2 row4 

Prueba anti_join from dplyr

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

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

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

EDITAR: Starting data.table v1.9.6 + podemos unir data.tables sin configurar las teclas mientras usamos

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

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

 fsetdiff(df, df1, all = TRUE) 

Pruebe el comando %in% y revíselo con !

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

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 se imaginaría; tome ambos argumentos como conjuntos y elimine todos los elementos en el segundo del primero.

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

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

enter image description here

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 aquí.

Otra opción es 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) 
    Intereting Posts