Eu tenho os seguintes 2 data.frames:
a1 <- data.frame(a = 1:5, b=letters[1:5])
a2 <- data.frame(a = 1:3, b=letters[1:3])
Eu quero encontrar a linha a1 tem que a2 não.
Existe uma função integrada para esse tipo de operação?
(ps: eu escrevi uma solução para isso, estou simplesmente curioso para saber se alguém já criou um código mais criado)
Aqui está a minha solução:
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)
a2 <- data.frame(a = c(1:3, 1), b = c(letters[1:3], "c"))
. Deixea1
o mesmo. Agora tente a comparação. Não está claro para mim, mesmo lendo as opções, qual é a maneira correta de listar apenas elementos comuns.SQLDF
fornece uma boa soluçãoE as linhas que estão nos dois quadros de dados:
A nova versão do
dplyr
tem uma função,anti_join
exatamente para esse tipo de comparaçãoE
semi_join
para filtrar linhasa1
que também estão ema2
fonte
anti_join
esemi_join
!No dplyr :
Basicamente,
setdiff(bigFrame, smallFrame)
você obtém os registros extras na primeira tabela.No SQLverse, isso é chamado de
Para obter boas descrições de todas as opções de junção e definir assuntos, este é um dos melhores resumos que já vi reunidos até hoje: http://www.vertabelo.com/blog/technical-articles/sql-joins
Mas voltando a esta pergunta - eis os resultados do
setdiff()
código ao usar os dados do OP:Ou você ainda
anti_join(a1,a2)
terá os mesmos resultados.Para mais informações: https://www.rstudio.com/wp-content/uploads/2015/02/data-wrangling-cheatsheet.pdf
fonte
a1
que não estãoa2
, você não deseja usar algo parecidosemi_join(a1, a2, by = c('a','b'))
? Na resposta de "Rickard", vejo que issosemi_join
foi sugerido.setdiff()
que oculta a função base que funciona em dois vetores: stat.ethz.ch/R-manual/R-devel/library/base/html/sets.html . Talvez você tenha carregado a biblioteca de lubrificados após o dplyr e está sugerindo isso como a fonte na listagem de tabcomplete?Certamente não é eficiente para esse propósito específico, mas o que costumo fazer nessas situações é inserir variáveis indicadoras em cada data.frame e depois mesclar:
valores ausentes em included_a1 observarão quais linhas estão faltando em a1. da mesma forma para a2.
Um problema com sua solução é que os pedidos das colunas devem corresponder. Outro problema é que é fácil imaginar situações em que as linhas são codificadas da mesma forma quando na verdade são diferentes. A vantagem de usar a mesclagem é que você obtém gratuitamente toda a verificação de erros necessária para uma boa solução.
fonte
included_a1
? : - /Eu escrevi um pacote ( https://github.com/alexsanjoseph/compareDF ) desde que tive o mesmo problema.
Um exemplo mais complicado:
O pacote também possui um comando html_output para verificação rápida
fonte
The two data frames have different columns!
Você pode usar o
daff
pacote (que envolve adaff.js
biblioteca usando oV8
pacote ):produz o seguinte objeto de diferença:
O formato diff é descrito no formato diff da marca-texto Coopy para tabelas e deve ser bastante auto-explicativo. As linhas com
+++
na primeira coluna@@
são as que são novasa1
e não estão presentesa2
.O objeto de diferença pode ser usado para
patch_data()
armazenar a diferença para fins de documentação usandowrite_diff()
ou para visualizar a diferença usandorender_diff()
:gera uma saída HTML pura:
fonte
Usando o
diffobj
pacote:fonte
Eu adaptei a
merge
função para obter essa funcionalidade. Em quadros de dados maiores, ele usa menos memória que a solução de mesclagem completa. E eu posso brincar com os nomes das colunas principais.Outra solução é usar a biblioteca
prob
.fonte
Seus dados de exemplo não possuem duplicatas, mas sua solução lida com eles automaticamente. Isso significa que, potencialmente, algumas das respostas não corresponderão aos resultados da sua função no caso de duplicatas.
Aqui está minha solução cujo endereço é duplicado da mesma maneira que o seu. Também escala ótimo!
Precisa de data.table 1.9.8+
fonte
Talvez seja muito simplista, mas usei essa solução e acho muito útil quando tenho uma chave primária que posso usar para comparar conjuntos de dados. Espero que possa ajudar.
fonte
Mais uma solução baseada em match_df no plyr. Aqui está o match_df de plyr:
Podemos modificá-lo para negar:
Então:
fonte
Usando
subset
:fonte
O código a seguir usa ambos
data.table
efastmatch
para aumentar a velocidade.fonte