web-dev-qa-db-fra.com

Python (pandas): suppression des doublons basés sur deux colonnes en conservant la ligne avec la valeur maximale dans une autre

J'ai un dataframe qui contient des valeurs en double selon deux colonnes (A et B):

A B C
1 2 1
1 2 4
2 7 1
3 4 0
3 4 8

Je veux supprimer les doublons en conservant la ligne avec la valeur maximale dans la colonne C. Cela entraînerait: 

A B C
1 2 4
2 7 1
3 4 8

Je n'arrive pas à comprendre comment faire ça. Devrais-je utiliser drop_duplicates(), autre chose?

29
Elsalex

Vous pouvez le faire en utilisant group by:

c_maxes = df.groupby(['A', 'B']).C.transform(max)
df = df.loc[df.C == c_maxes]

c_maxes est une Series des valeurs maximales de C dans chaque groupe, mais a la même longueur et le même index que df. Si vous n'avez pas utilisé .transform, alors imprimer c_maxes pourrait être une bonne idée de voir comment cela fonctionne. 

Une autre approche utilisant drop_duplicates serait 

df.sort('C').drop_duplicates(subset=['A', 'B'], take_last=True)

Je ne sais pas ce qui est le plus efficace, mais je suppose que la première approche n’implique pas de tri. 

EDIT: À partir de pandas 0.18 la deuxième solution serait 

df.sort_values('C').drop_duplicates(subset=['A', 'B'], keep='last')

ou bien,

df.sort_values('C', ascending=False).drop_duplicates(subset=['A', 'B'])

Dans tous les cas, la solution groupby semble être nettement plus performante: 

%timeit -n 10 df.loc[df.groupby(['A', 'B']).C.max == df.C]
10 loops, best of 3: 25.7 ms per loop

%timeit -n 10 df.sort_values('C').drop_duplicates(subset=['A', 'B'], keep='last')
10 loops, best of 3: 101 ms per loop
43
JoeCondron

Je pense que groupby devrait fonctionner.

df.groupby(['A', 'B']).max()['C']

Si vous avez besoin d'une image de données, vous pouvez chaîner l'appel de réinitialisation d'index.

df.groupby(['A', 'B']).max()['C'].reset_index()
9
b10n

Vous pouvez le faire simplement en utilisant la fonction de doublons de pandas

df.drop_duplicates(['A','B'],keep= 'last')
3
Sudharsan

Vous pouvez le faire avec drop_duplicates comme vous le souhaitiez

# initialisation
d = pd.DataFrame({'A' : [1,1,2,3,3], 'B' : [2,2,7,4,4],  'C' : [1,4,1,0,8]})

d = d.sort_values("C", ascending=False)
d = d.drop_duplicates(["A","B"])

S'il est important d'obtenir le même ordre 

d = d.sort_index()
1
AlexT