Eu tenho dois quadros de dados de pandas que têm algumas linhas em comum.
Suponha que dataframe2 seja um subconjunto de dataframe1.
Como posso obter as linhas do dataframe1 que não estão no dataframe2?
df1 = pandas.DataFrame(data = {'col1' : [1, 2, 3, 4, 5], 'col2' : [10, 11, 12, 13, 14]})
df2 = pandas.DataFrame(data = {'col1' : [1, 2, 3], 'col2' : [10, 11, 12]})
Respostas:
Um método seria armazenar o resultado de um formulário de mesclagem interna de ambos os dfs; então, podemos simplesmente selecionar as linhas quando os valores de uma coluna não estiverem tão comuns:
EDITAR
Outro método que você encontrou é usar o
isin
que produziráNaN
linhas que você pode soltar:No entanto, se o df2 não iniciar linhas da mesma maneira, isso não funcionará:
produzirá o df inteiro:
fonte
df1[~df1.isin(df2)].dropna(how = 'all')
parece fazer o truque. De qualquer forma, obrigado - sua resposta me ajudou a encontrar uma solução.isin
requer que ambos os dfs começar com os mesmos valores de linha assim, por exemplo, se df2 eradf2 = pd.DataFrame(data = {'col1' : [2, 3,4], 'col2' : [11,12, 13]})
então o seu método não vai funcionarkeep=False
:df0.append(df1).drop_duplicates(keep=False)
, por padrão, ele mantém o primeiro duplicado, você quer deixar cair todas as duplicatasA solução atualmente selecionada produz resultados incorretos. Para resolver corretamente esse problema, podemos executar uma junção esquerda de
df1
paradf2
, certificando-se de obter primeiro apenas as linhas exclusivasdf2
.Primeiro, precisamos modificar o DataFrame original para adicionar a linha aos dados [3, 10].
Execute uma junção esquerda, eliminando duplicatas
df2
para que cada linha dedf1
junções tenha exatamente 1 linha dedf2
. Use o parâmetroindicator
para retornar uma coluna extra indicando de qual tabela a linha era.Crie uma condição booleana:
Por que outras soluções estão erradas
Algumas soluções cometem o mesmo erro - elas apenas verificam se cada valor está independentemente em cada coluna, não juntas na mesma linha. A adição da última linha, única, mas com os valores de ambas as colunas,
df2
expõe o erro:Esta solução obtém o mesmo resultado errado:
fonte
df_all[df_all['_merge'] == 'left_only']
a ter uma df com os resultadosSupondo que os índices sejam consistentes nos quadros de dados (sem levar em consideração os valores reais da coluna):
fonte
df1
quais os índices NÃO estãodf2.index
". Mais sobre negação: stackoverflow.com/q/19960077/304209 (surpreendentemente, não consegui encontrar nenhuma menção a til nos documentos do pandas).ValueError: Item wrong length x instead of y.
Como já foi sugerido, o isin exige que as colunas e os índices sejam os mesmos para uma correspondência. Se a correspondência só deve estar no conteúdo das linhas, uma maneira de obter a máscara para filtrar as linhas presentes é convertê-las em um (Multi) Índice:
Se o índice deve ser levado em consideração, set_index possui um argumento de palavra-chave anexado para anexar colunas ao índice existente. Se as colunas não se alinharem, a lista (df.columns) poderá ser substituída pelas especificações da coluna para alinhar os dados.
alternativamente, poderia ser usado para criar os índices, embora eu duvide que isso seja mais eficiente.
fonte
Suponha que você tenha dois quadros de dados, df_1 e df_2 com vários campos (nome_da_coluna) e deseje encontrar apenas as entradas no df_1 que não estão no df_2 com base em alguns campos (por exemplo, campos_x, campos_y), siga as etapas a seguir.
Etapa1.Adicione uma coluna key1 e key2 a df_1 e df_2 respectivamente.
Etapa 2.Merge os quadros de dados conforme mostrado abaixo. field_x e field_y são nossas colunas desejadas.
Etapa 3. Selecione apenas as linhas de df_1 em que chave1 não é igual a chave2.
Passo4.Drop chave1 e chave2.
Este método resolverá seu problema e funciona rapidamente, mesmo com grandes conjuntos de dados. Eu tentei para quadros de dados com mais de 1.000.000 de linhas.
fonte
um pouco tarde, mas pode valer a pena verificar o parâmetro "indicator" do pd.merge.
Veja esta outra pergunta para um exemplo: Compare os PandaS DataFrames e retorne as linhas ausentes do primeiro
fonte
você pode fazer isso usando o método isin (dict) :
Explicação:
fonte
Você também pode concat
df1
,df2
:e remova todas as duplicatas:
fonte
Que tal agora:
fonte
Aqui está outra maneira de resolver isso:
Ou:
fonte
Minha maneira de fazer isso envolve adicionar uma nova coluna exclusiva a um dataframe e usá-la para escolher se deseja manter uma entrada
Isso faz com que cada entrada no df1 tenha um código - 0 se for exclusivo do df1, 1 se estiver nos dois DataFrames. Você então usa isso para restringir o que deseja
fonte
fonte