Encontre o complemento de um quadro de dados (anti-join)

Eu tenho dois frameworks de dados (df e df1). df1 é um subconjunto de df. Eu quero obter um quadro de dados que é complemento de df1 em df, ou seja, linhas de retorno do primeiro dataset que não são correspondidos no segundo. Por exemplo, vamos

quadro de dados df:

heads row1 row2 row3 row4 row5 

quadro de dados df1:

 heads row3 row5 

Então a saída desejada df2 é:

 heads row1 row2 row4 

Tente anti_join de dplyr

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

Você também pode fazer algum tipo de anti-join com a data.table binária do data.table

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

EDIT: Iniciando dados.table v1.9.6 + podemos juntar dados.tables sem definir as chaves enquanto estiver usando on

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

EDIT2: Iniciando o data.table v1.9.8 + fsetdiff foi introduzido, o que é basicamente uma variação da solução acima, apenas sobre todos os nomes das colunas do x data.table, por exemplo x[!y, on = names(x)] . Se all estiver definido como FALSE (o comportamento padrão), somente linhas exclusivas em x serão retornadas. Para o caso de apenas uma coluna em cada data.table o seguinte será equivalente às soluções anteriores

 fsetdiff(df, df1, all = TRUE) 

Experimente o comando %in% e inverta-o !

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

Outra opção, usando a base R e a function setdiff :

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

setdiff funciona exatamente como você imaginaria; Pegue ambos os argumentos como conjuntos e remova todos os itens no segundo do primeiro.

Eu acho o setdiff mais legível %in% e prefiro não precisar de bibliotecas adicionais quando não preciso delas, mas a resposta que você usa é basicamente uma questão de gosto pessoal.

dplyr também tem setdiff() que vai te dar o

insira a descrição da imagem aqui

setdiff(bigFrame, smallFrame) obtém os registros extras na primeira tabela.

Assim, para o exemplo do OP, o código seria setdiff(df, df1)

O dplyr tem uma grande funcionalidade: para um guia rápido e fácil, veja aqui.

Outra opção, criando uma function negate_match_df , manipulando o código de match_df do pacote 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] } 

Dados

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

Saída

 negate_match_df(df,df1)