Come ottengo un elenco di tutti gli elementi duplicati utilizzando i panda in Python?


128

Ho un elenco di articoli che probabilmente presentano alcuni problemi di esportazione. Vorrei ottenere un elenco degli elementi duplicati in modo da poterli confrontare manualmente. Quando provo a utilizzare il metodo duplicato dei panda , restituisce solo il primo duplicato. C'è un modo per ottenere tutti i duplicati e non solo il primo?

Una piccola sottosezione del mio set di dati è simile a questa:

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

Il mio codice è attualmente simile a questo:

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

Ci sono un paio di elementi duplicati. Ma, quando utilizzo il codice sopra, ottengo solo il primo elemento. Nel riferimento API, vedo come posso ottenere l'ultimo elemento, ma vorrei averli tutti in modo da poterli ispezionare visivamente per vedere perché ottengo la discrepanza. Quindi, in questo esempio vorrei ottenere tutte e tre le voci A036 e sia 11795 voci che qualsiasi altra voce duplicata, invece della prima. Qualsiasi aiuto è molto apprezzato.


1
"Duplicati" può significare varie cose "Nel tuo caso, vuoi considerare solo i duplicati in una singola colonnaID , non" righe identiche in più o tutte le colonne ".
smci

Risposte:


170

Metodo n. 1: stampa tutte le righe in cui l'ID è uno degli ID duplicati:

>>> 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

ma non riuscivo a pensare a un modo carino per evitare di ripetere idscosì tante volte. Preferisco il metodo n. 2: groupbysull'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

11
Il metodo n. 2 è semplicemente perfetto! Grazie mille.
BigHandsome

4
Il metodo n. 2 fallisce ("Nessun oggetto da concatenare") se non ci sono duplicati
CPBL

4
cosa fa g for _ ?
user77005

5
@ user77005 si potrebbe hai capito già, ma a beneficio di tutti, si legge come questo: g for (placeholder, g) in df.groupby('bla') if 'bla'; il carattere di sottolineatura è un tipico simbolo per segnaposto di un argomento inevitabile in cui non vogliamo usarlo per nulla in un'espressione simile a lambda.
stucash

7
Il metodo n. 1 deve essere aggiornato: è sortstato deprecato per DataFrames a favore di uno sort_valueso dei sort_index correlati SO Q&A
tatlar

138

Con la versione 0.17 di Pandas, puoi impostare "keep = False" nella funzione duplicata per ottenere tutti gli elementi duplicati.

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

3
Bingo, ecco la risposta. Quindi: str o str o booleano ... strana scelta API. 'all'sarebbe più logico e intuitivo IMO.
Jarad

92
df[df.duplicated(['ID'], keep=False)]

ti restituirà tutte le righe duplicate.

Secondo la documentazione :

keep: {'first', 'last', False}, default 'first'

  • primo: contrassegna i duplicati come True tranne per la prima occorrenza.
  • last: contrassegna i duplicati come True tranne che per l'ultima occorrenza.
  • Falso: contrassegna tutti i duplicati come True.

@dreme questo non è sintaticamente corretto, né funziona. Non corrisponde a "]" e inoltre non restituisce ciò di cui hanno bisogno. È più corto, ma sbagliato.
FinancialRadDeveloper

Oops, hai ragione @FinancialRadDeveloper, su entrambi i fronti. Cancellerò il mio commento. Grazie per aver rilevato l'errore.
dreme

3
df [df ['ID']. duplicated () == True] Questo restituirà tutti i duplicati
Hariprasad

12

Poiché non sono in grado di commentare, quindi invio come risposta separata

Per trovare duplicati sulla base di più di una colonna, menziona il nome di ogni colonna come di seguito e ti restituirà tutte le righe duplicate impostate:

df[df[['product_uid', 'product_title', 'user']].duplicated() == True]

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

Questo ha funzionato per me


2
In realtà non è necessario aggiungere == True, .duplicated()restituisce già l'array bool.
Jakub Wagner

3

Usando un elemento logico o e impostando l'argomento take_last del metodo duplicato dei panda sia su True che su False puoi ottenere un set dal tuo dataframe che include tutti i duplicati.

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

2

Questa potrebbe non essere una soluzione alla domanda, ma per illustrare esempi:

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)

Le uscite:

   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

2

sort("ID")non sembra funzionare ora, sembra deprecato come da documento di ordinamento , quindi usa sort_values("ID")invece per ordinare dopo il filtro duplicato, come segue:

df[df.ID.duplicated(keep=False)].sort_values("ID")

2

Per il mio database duplicato (keep = False) non ha funzionato fino a quando la colonna non è stata ordinata.

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

1

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


4
Per favore, puoi estendere la tua risposta con una spiegazione più dettagliata? Questo sarà molto utile per la comprensione. Grazie!
vezunchik

Benvenuto in Stack Overflow e grazie per il tuo contributo! Sarebbe gentile se potessi estendere la tua risposta con una spiegazione. Qui trovi una guida su come dare una buona risposta . Grazie!
David
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.