3
votes

Pandas - À l'opposé des doublons, gardez d'abord

Je suis familier avec la suppression des lignes en double, puis en utilisant le paramètre first , last , none . Rien de bien compliqué avec cela et il y a beaucoup d'exemples (c'est-à-dire ici ) .

Cependant, ce que je recherche, c'est qu'il existe un moyen de trouver les doublons, mais au lieu de supprimer tous les doublons et de conserver le premier, si j'ai des doublons, conservez tous les doublons mais supprimez le premier:

Donc au lieu de "supprimer si les doublons, conserver le premier", je veux "conserver si les doublons, déposer en premier"

Exemple:

Compte tenu de cette base de données, et en regardant les doublons dans Colonne cost :

import pandas as pd

df = pd.DataFrame([
['0',   'a',    'bb',   '1'],
['1',   'a',    'cc',   '2'],
['1_0', 'a',    'dd',   '2'],
['2',   'a',    'ee',   '3'],
['2_0', 'a',    'ff',   '3'],
['2_1', 'a',    'gg',   '3'],
['2_2', 'a',    'hh',   '3']], columns = ['ID', 'name', 'type', 'cost'])

S'il y a des doublons dans la colonne cost , supprimez simplement la première occurrence, mais gardez le reste.

Donc, ma sortie serait:

    ID name type cost
0    0    a   bb    1
2  1_0    a   dd    2
4  2_0    a   ff    3
5  2_1    a   gg    3
6  2_2    a   hh    3

Voici l'exemple de dataframe:

    ID name type cost
0    0    a   bb    1
1    1    a   cc    2 <--- there are duplicates, so drop this row
2  1_0    a   dd    2
3    2    a   ee    3 <--- there are duplicates, so drop this row
4  2_0    a   ff    3
5  2_1    a   gg    3
6  2_2    a   hh    3

p >


0 commentaires

4 Réponses :


4
votes

Vous pouvez chaîner 2 masques créés par DataFrame.duplicated avec OR au niveau du bit et filtrer par indexation booléenne :

print (df.assign(mask1=df.duplicated('cost'), mask2=~df.duplicated('cost', keep=False)))
    ID name type cost  mask1  mask2
0    0    a   bb    1  False   True
1    1    a   cc    2  False  False
2  1_0    a   dd    2   True  False
3    2    a   ee    3  False  False
4  2_0    a   ff    3   True  False
5  2_1    a   gg    3   True  False
6  2_2    a   hh    3   True  False

Détail :

df = df[df.duplicated('cost') | ~df.duplicated('cost', keep=False)]
print (df)
    ID name type cost
0    0    a   bb    1
2  1_0    a   dd    2
4  2_0    a   ff    3
5  2_1    a   gg    3
6  2_2    a   hh    3


1 commentaires

Ah ok. Ensuite, il supprime simplement toutes les lignes où les deux sont False. je l'ai.



1
votes

Vous pouvez faire ce qui suit avec l'opérateur XOR (^) qui recherche que les deux conditions soient vraies. Puisque nous utilisons l'opérateur NOT (~) . Il recherche le contraire, par exemple: à la fois False :

    ID name type cost
0    0    a   bb    1
2  1_0    a   dd    2
4  2_0    a   ff    3
5  2_1    a   gg    3
6  2_2    a   hh    3

df[~(df.cost.duplicated(keep=False) ^ df.cost.duplicated())]

p>


0 commentaires

1
votes

Vous pouvez utiliser groupby et passer une fonction lambda pour récupérer les enregistrements après la première duplication si la duplication existe:

>>> df.groupby('cost').apply(lambda group: group.iloc[1:] if len(group) > 1 else group).reset_index(drop=True)
    ID  cost name type
0    0     1    a   bb
1  1_0     2    a   dd
2  2_0     3    a   ff
3  2_1     3    a   gg
4  2_2     3    a   hh


0 commentaires

0
votes

Vous pouvez utiliser le code suivant:

# Import pandas library 
import pandas as pd 

# initialize list of lists so i can create duplicate datas
data = [['tom', 10], ['nick', 15], ['juli', 14], ['nick', 15], ['julia', 140],
        ['tom', 10],['tom', 10],['tom', 10]] 

# Create the pandas DataFrame 
df = pd.DataFrame(data, columns = ['Name', 'Age']) 

# print dataframe. 
print(df)

# Now the logic begins from here

colnames=[]

for col in df.columns:
    colnames.append(col)


listdf=df.values.tolist()
temp=[]

for i in range(0,len(listdf)):
    if(listdf.count(listdf[i])>1 and listdf[i] not in temp):
        temp.append(listdf[i])

df = pd.DataFrame(temp, columns =colnames)

print("dataframe with only duplciates ")
print(df)


0 commentaires