Como faço para obter uma lista de todos os itens duplicados usando pandas em python?

126

Tenho uma lista de itens que provavelmente apresentam alguns problemas de exportação. Gostaria de obter uma lista dos itens duplicados para poder compará-los manualmente. Quando tento usar o método duplicado do pandas , ele retorna apenas a primeira duplicata. Existe uma maneira de obter todas as duplicatas e não apenas a primeira?

Uma pequena subseção do meu conjunto de dados se parece com isto:

ID,ENROLLMENT_DATE,TRAINER_MANAGING,TRAINER_OPERATOR,FIRST_VISIT_DATE
1536D,12-Feb-12,"06DA1B3-Lebanon NH",,15-Feb-12
F15D,18-May-12,"06405B2-Lebanon NH",,25-Jul-12
8096,8-Aug-12,"0643D38-Hanover NH","0643D38-Hanover NH",25-Jun-12
A036,1-Apr-12,"06CB8CF-Hanover NH","06CB8CF-Hanover NH",9-Aug-12
8944,19-Feb-12,"06D26AD-Hanover NH",,4-Feb-12
1004E,8-Jun-12,"06388B2-Lebanon NH",,24-Dec-11
11795,3-Jul-12,"0649597-White River VT","0649597-White River VT",30-Mar-12
30D7,11-Nov-12,"06D95A3-Hanover NH","06D95A3-Hanover NH",30-Nov-11
3AE2,21-Feb-12,"06405B2-Lebanon NH",,26-Oct-12
B0FE,17-Feb-12,"06D1B9D-Hartland VT",,16-Feb-12
127A1,11-Dec-11,"064456E-Hanover NH","064456E-Hanover NH",11-Nov-12
161FF,20-Feb-12,"0643D38-Hanover NH","0643D38-Hanover NH",3-Jul-12
A036,30-Nov-11,"063B208-Randolph VT","063B208-Randolph VT",
475B,25-Sep-12,"06D26AD-Hanover NH",,5-Nov-12
151A3,7-Mar-12,"06388B2-Lebanon NH",,16-Nov-12
CA62,3-Jan-12,,,
D31B,18-Dec-11,"06405B2-Lebanon NH",,9-Jan-12
20F5,8-Jul-12,"0669C50-Randolph VT",,3-Feb-12
8096,19-Dec-11,"0649597-White River VT","0649597-White River VT",9-Apr-12
14E48,1-Aug-12,"06D3206-Hanover NH",,
177F8,20-Aug-12,"063B208-Randolph VT","063B208-Randolph VT",5-May-12
553E,11-Oct-12,"06D95A3-Hanover NH","06D95A3-Hanover NH",8-Mar-12
12D5F,18-Jul-12,"0649597-White River VT","0649597-White River VT",2-Nov-12
C6DC,13-Apr-12,"06388B2-Lebanon NH",,
11795,27-Feb-12,"0643D38-Hanover NH","0643D38-Hanover NH",19-Jun-12
17B43,11-Aug-12,,,22-Oct-12
A036,11-Aug-12,"06D3206-Hanover NH",,19-Jun-12

Meu código se parece com este atualmente:

df_bigdata_duplicates = df_bigdata[df_bigdata.duplicated(cols='ID')]

Existem alguns itens duplicados. Mas, quando uso o código acima, recebo apenas o primeiro item. Na referência da API, vejo como posso obter o último item, mas gostaria de ter todos eles para que possa inspecioná-los visualmente para ver por que estou obtendo a discrepância. Portanto, neste exemplo, gostaria de obter todas as três entradas A036 e 11795 entradas e quaisquer outras entradas duplicadas, em vez de apenas a primeira. Qualquer ajuda é muito apreciada.

BigHandsome
fonte
1
"Duplicatas" podem significar várias coisas "No seu caso, você só deseja considerar duplicatas em uma única colunaID , não" linhas idênticas em múltiplas ou todas as colunas ".
smci

Respostas:

169

Método # 1: imprima todas as linhas onde o ID é um dos IDs duplicados:

>>> import pandas as pd
>>> df = pd.read_csv("dup.csv")
>>> ids = df["ID"]
>>> df[ids.isin(ids[ids.duplicated()])].sort("ID")
       ID ENROLLMENT_DATE        TRAINER_MANAGING        TRAINER_OPERATOR FIRST_VISIT_DATE
24  11795       27-Feb-12      0643D38-Hanover NH      0643D38-Hanover NH        19-Jun-12
6   11795        3-Jul-12  0649597-White River VT  0649597-White River VT        30-Mar-12
18   8096       19-Dec-11  0649597-White River VT  0649597-White River VT         9-Apr-12
2    8096        8-Aug-12      0643D38-Hanover NH      0643D38-Hanover NH        25-Jun-12
12   A036       30-Nov-11     063B208-Randolph VT     063B208-Randolph VT              NaN
3    A036        1-Apr-12      06CB8CF-Hanover NH      06CB8CF-Hanover NH         9-Aug-12
26   A036       11-Aug-12      06D3206-Hanover NH                     NaN        19-Jun-12

mas não consegui pensar em uma maneira legal de evitar a repetição idstantas vezes. Prefiro o método 2: groupbyno ID.

>>> pd.concat(g for _, g in df.groupby("ID") if len(g) > 1)
       ID ENROLLMENT_DATE        TRAINER_MANAGING        TRAINER_OPERATOR FIRST_VISIT_DATE
6   11795        3-Jul-12  0649597-White River VT  0649597-White River VT        30-Mar-12
24  11795       27-Feb-12      0643D38-Hanover NH      0643D38-Hanover NH        19-Jun-12
2    8096        8-Aug-12      0643D38-Hanover NH      0643D38-Hanover NH        25-Jun-12
18   8096       19-Dec-11  0649597-White River VT  0649597-White River VT         9-Apr-12
3    A036        1-Apr-12      06CB8CF-Hanover NH      06CB8CF-Hanover NH         9-Aug-12
12   A036       30-Nov-11     063B208-Randolph VT     063B208-Randolph VT              NaN
26   A036       11-Aug-12      06D3206-Hanover NH                     NaN        19-Jun-12
DSM
fonte
11
Método # 2 é simplesmente perfeito! Muito obrigado.
BigHandsome
4
Método # 2 falha ("Nenhum objeto para concatenar") se não houver duplicatas
CPBL
4
o que g for _ faz?
user77005
5
@ user77005 que você pode descobri já, mas para benefício de todos, ele lê como este: g for (placeholder, g) in df.groupby('bla') if 'bla'; o sublinhado é um símbolo típico para placeholder de um argumento inevitável onde não queremos usá-lo para nada em uma expressão semelhante a lambda.
stucash 01 de
7
O método nº 1 precisa ser atualizado: sortfoi descontinuado para DataFrames em favor de um sort_valuesou de um sort_index relacionado SO Q&A
tatlar de
138

Com o Pandas versão 0.17, você pode definir 'keep = False' na função duplicada para obter todos os itens duplicados.

In [1]: import pandas as pd

In [2]: df = pd.DataFrame(['a','b','c','d','a','b'])

In [3]: df
Out[3]: 
       0
    0  a
    1  b
    2  c
    3  d
    4  a
    5  b

In [4]: df[df.duplicated(keep=False)]
Out[4]: 
       0
    0  a
    1  b
    4  a
    5  b
usuário666
fonte
3
Bingo, aí está a resposta. Então: str ou str ou boolean ... escolha de API estranha. 'all'seria IMO mais lógico e intuitivo.
Jarad de
92
df[df.duplicated(['ID'], keep=False)]

ele retornará todas as linhas duplicadas de volta para você.

De acordo com a documentação :

manter: {'primeiro', 'último', falso}, padrão 'primeiro'

  • primeiro: marcar duplicatas como verdadeiras, exceto para a primeira ocorrência.
  • último: marca duplicatas como verdadeiras, exceto para a última ocorrência.
  • Falso: marque todas as duplicatas como verdadeiras.
Kelly ChowChow
fonte
@dreme isso não está sintaticamente correto, nem funciona. Incompatibilidade ']' e também não retorna o que eles precisam. É mais curto, mas errado.
FinancialRadDeveloper
Opa, você está certo @FinancialRadDeveloper, em ambos os casos. Vou deletar meu comentário. Obrigado por identificar o erro.
dreme
3
df [df ['ID']. duplicated () == True] Isso retornará todas as duplicatas
Hariprasad
12

Como não posso comentar, postarei como uma resposta separada

Para encontrar duplicatas com base em mais de uma coluna, mencione cada nome de coluna conforme abaixo, e ele retornará a você todas as linhas duplicadas definidas:

df[df[['product_uid', 'product_title', 'user']].duplicated() == True]
Deepak
fonte
10
df[df['ID'].duplicated() == True]

Isso funcionou para mim

Hariprasad
fonte
2
Na verdade, você não precisa adicionar == True, .duplicated()já retorna o array bool.
Jakub Wagner
3

Usando um elemento lógico ou e definindo o argumento take_last do método duplicated pandas para True e False, você pode obter um conjunto de seu dataframe que inclui todas as duplicatas.

df_bigdata_duplicates = 
    df_bigdata[df_bigdata.duplicated(cols='ID', take_last=False) |
               df_bigdata.duplicated(cols='ID', take_last=True)
              ]
Oshbocker
fonte
2

Isso pode não ser uma solução para a questão, mas para ilustrar exemplos:

import pandas as pd

df = pd.DataFrame({
    'A': [1,1,3,4],
    'B': [2,2,5,6],
    'C': [3,4,7,6],
})

print(df)
df.duplicated(keep=False)
df.duplicated(['A','B'], keep=False)

As saídas:

   A  B  C
0  1  2  3
1  1  2  4
2  3  5  7
3  4  6  6

0    False
1    False
2    False
3    False
dtype: bool

0     True
1     True
2    False
3    False
dtype: bool
yoonghm
fonte
2

sort("ID")não parece estar funcionando agora, parece obsoleto de acordo com o documento de classificação , então use sort_values("ID")para classificar após o filtro duplicado, da seguinte maneira:

df[df.ID.duplicated(keep=False)].sort_values("ID")
Nafeez Quraishi
fonte
2

Para meu banco de dados duplicado (manter = Falso) não funcionou até que a coluna fosse classificada.

data.sort_values(by=['Order ID'], inplace=True)
df = data[data['Order ID'].duplicated(keep=False)]
LetzerWille
fonte
1

df[df.duplicated(['ID'])==True].sort_values('ID')

PREM JILLA
fonte
4
Por favor, você pode estender sua resposta com uma explicação mais detalhada? Isso será muito útil para a compreensão. Obrigado!
vezunchik
Bem-vindo ao Stack Overflow e obrigado por sua contribuição! Seria bom se você pudesse estender sua resposta com uma explicação. Aqui você encontra um guia Como dar uma boa resposta . Obrigado!
David