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.