Comment obtenir une liste de tous les éléments en double à l'aide de pandas en python?


129

J'ai une liste d'articles qui ont probablement des problèmes d'exportation. Je souhaite obtenir une liste des éléments en double afin de pouvoir les comparer manuellement. Lorsque j'essaie d'utiliser la méthode dupliquée pandas , elle ne renvoie que le premier duplicata. Existe-t-il un moyen d'obtenir tous les doublons et pas seulement le premier?

Une petite sous-section de mon ensemble de données ressemble à ceci:

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

Mon code ressemble à ceci actuellement:

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

Il y a quelques éléments en double. Mais, lorsque j'utilise le code ci-dessus, je n'obtiens que le premier élément. Dans la référence de l'API, je vois comment je peux obtenir le dernier élément, mais j'aimerais tous les avoir afin que je puisse les inspecter visuellement pour voir pourquoi j'obtiens l'écart. Donc, dans cet exemple, je voudrais obtenir les trois entrées A036 et les deux 11795 entrées et toutes les autres entrées dupliquées, au lieu de la première. Toute aide est très appréciée.


1
"Les doublons" peuvent signifier différentes choses "Dans votre cas, vous ne voulez que considérer doublons dans une seule colonneID , pas" les lignes identiques dans plusieurs colonnes ou toutes les colonnes ".
smci

Réponses:


170

Méthode n ° 1: imprimez toutes les lignes où l'ID est l'un des ID en double:

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

mais je ne pouvais pas penser à une bonne façon d'éviter de répéter ids autant de fois. Je préfère la méthode n ° 2: groupbysur l'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
La méthode n ° 2 est tout simplement parfaite! Merci beaucoup.
BigHandsome

4
La méthode n ° 2 échoue ("Aucun objet à concaténer") s'il n'y a pas de dups
CPBL

4
que fait g for _ quoi?
user77005

5
@ user77005 vous avez peut - être déjà compris, mais pour le bénéfice de tous, il se lit comme suit: g for (placeholder, g) in df.groupby('bla') if 'bla'; le trait de soulignement est un symbole typique pour l'espace réservé d'un argument inévitable où nous ne voulons pas l'utiliser pour quoi que ce soit dans une expression de type lambda.
stucash

7
La méthode n ° 1 doit être mise à jour: a sortété déconseillée pour DataFrames en faveur de l'un sort_valuesou l' autre ou sort_index des questions-réponses SO liées
Tatlar

138

Avec Pandas version 0.17, vous pouvez définir 'keep = False' dans la fonction dupliquée pour obtenir tous les éléments en double.

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, voici la réponse. Donc: str ou str ou boolean ... choix d'API étrange. 'all'serait l'OMI plus logique et intuitive.
Jarad

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

il vous renverra toutes les lignes dupliquées.

Selon la documentation :

keep: {'first', 'last', False}, par défaut 'first'

  • first: marquez les doublons comme True sauf pour la première occurrence.
  • last: marque les doublons comme True sauf pour la dernière occurrence.
  • False: marquez tous les doublons comme True.

@dreme ce n'est pas syntatiquement correct et cela ne fonctionne pas non plus. Mismatching ']' et il ne renvoie pas non plus ce dont ils ont besoin. C'est plus court, mais faux.
FinancialRadDeveloper

Oups, vous avez raison @FinancialRadDeveloper, sur les deux plans. Je supprimerai mon commentaire. Merci d'avoir détecté l'erreur.
dreme

4
df [df ['ID']. duplicated () == True] Cela renverra tous les doublons
Hariprasad

12

Comme je ne peux pas commenter, donc poster comme réponse séparée

Pour trouver des doublons sur la base de plus d'une colonne, mentionnez chaque nom de colonne comme ci-dessous, et il vous renverra toutes les lignes dupliquées définies:

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

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

Cela a fonctionné pour moi


2
Vous n'avez en fait pas à ajouter == True, .duplicated()retourne déjà un tableau booléen.
Jakub Wagner le

3

En utilisant un élément logique ou et en définissant l'argument take_last de la méthode dupliquée pandas sur True et False, vous pouvez obtenir un ensemble de votre dataframe qui inclut tous les doublons.

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

2

Ce n'est peut-être pas une solution à la question, mais pour illustrer des exemples:

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)

Les sorties:

   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")ne semble pas fonctionner maintenant, semble obsolète selon le document de tri , alors utilisez sort_values("ID")plutôt pour trier après le filtre en double, comme suit:

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

2

Pour ma base de données dupliquée (keep = False) ne fonctionnait pas tant que la colonne n'était pas triée.

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
Pouvez-vous étendre votre réponse avec des explications plus détaillées? Cela sera très utile pour la compréhension. Je vous remercie!
vezunchik

Bienvenue sur Stack Overflow et merci pour votre contribution! Ce serait gentil si vous pouviez étendre votre réponse par une explication. Ici vous trouvez un guide Comment donner une bonne réponse . Merci!
David le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.