2012-09-19 26 views
58

Tengo un marco de datos con valores repetidos en la columna A. Quiero soltar duplicados, manteniendo la fila con el valor más alto en la columna B.python pandas: Eliminar duplicados por columnas A, manteniendo la fila con el valor más alto en la columna B

Así que esto:

A B 
1 10 
1 20 
2 30 
2 40 
3 10 

debe convertirse en esto:

A B 
1 20 
2 40 
3 10 

Wes ha añadido algunas funciones agradable para dejar duplicados: http://wesmckinney.com/blog/?p=340. Pero AFAICT está diseñado para duplicados exactos, por lo que no se mencionan los criterios para seleccionar qué filas se guardan.

Supongo que probablemente exista una manera fácil de hacerlo --- quizás tan fácil como ordenar el dataframe antes de descartar duplicados --- pero no conozco la lógica interna de groupby lo suficiente como para resolverlo. ¿Alguna sugerencia?

+1

Tenga en cuenta que la dirección URL en la pregunta aparece EOL. – DaveL17

+0

Para una forma idiomática y de rendimiento, [consulte esta solución a continuación] (https://stackoverflow.com/a/41650846/3707607). –

Respuesta

77

esto toma la última. No es la máxima de que:

In [10]: df.drop_duplicates(subset='A', keep="last") 
Out[10]: 
    A B 
1 1 20 
3 2 40 
4 3 10 

Usted también puede hacer algo como:

In [12]: df.groupby('A', group_keys=False).apply(lambda x: x.loc[x.B.idxmax()]) 
Out[12]: 
    A B 
A  
1 1 20 
2 2 40 
3 3 10 
+9

Nota pequeña: los parámetros 'cols' y' take_last' se deprecian y han sido reemplazados por los parámetros 'subset' y' keep'. http://pandas.pydata.org/pandas-docs/version/0.17.1/generated/pandas.DataFrame.drop_duplicates.html – Jezzamon

+0

como @Jezzamon dice: 'FutureWarning: la palabra clave take_last = True está en desuso, use keep = ' last 'instead' –

+0

¿Hay alguna razón para no usar 'df.sort_values ​​(by = ['B']). drop_duplicates (subconjunto = ['A'], keep = 'last')'? Quiero decir que este sort_values ​​parece seguro para mí, pero no tengo idea de si realmente es así. – josh

-3

no voy a dar la respuesta completa (no creo que usted está buscando el análisis y la escritura para presentar parte de todos modos), pero un indicio fundamental debería ser suficiente: la función de uso pitón set(), y luego sorted() o .sort() acoplado con .reverse():

>>> a=sorted(set([10,60,30,10,50,20,60,50,60,10,30])) 
>>> a 
[10, 20, 30, 50, 60] 
>>> a.reverse() 
>>> a 
[60, 50, 30, 20, 10] 
+6

Tal vez estoy equivocado en esto, pero la refundición de un Dataframe de pandas como un conjunto, y luego convertirlo de nuevo parece una forma muy ineficiente de resolver este problema.Estoy haciendo un análisis de registro, así que lo aplicaré a algunos conjuntos de datos muy grandes. – Abe

+0

Lo siento, no sé demasiado sobre este escenario en particular, por lo que es posible que mi respuesta genérica no resulte demasiado eficiente para su problema. –

7

Prueba esto:

df.groupby(['A']).max() 
+1

¿Conoces la mejor expresión idiomática para reindexar esto para que parezca el DataFrame original? Estaba tratando de resolver eso cuando me hiciste el ninja. : ^) – DSM

+3

aseado. ¿Qué sucede si el marco de datos contiene más columnas (por ejemplo, C, D, E)? Max no parece funcionar en ese caso, porque necesitamos especificar que B es la única columna que necesita maximizarse. – Abe

+1

@DSM Compruebe el enlace en la pregunta original. Hay algún código para reindexar el marco de datos agrupado. – Abe

12

La respuesta más común es hacer demasiado trabajo y parece ser muy lento para grandes conjuntos de datos. apply es lento y debe evitarse si es posible. ix está en desuso y debe evitarse también.

df.sort_values('B', ascending=False).drop_duplicates('A').sort_index() 

    A B 
1 1 20 
3 2 40 
4 3 10 

O simplemente agrupe por todas las otras columnas y tome el máximo de la columna que necesite. df.groupby('A', as_index=False).max()

0

esto también funciona:

a=pd.DataFrame({'A':a.groupby('A')['B'].max().index,'B':a.groupby('A')  ['B'].max().values}) 
+0

Si bien este fragmento de código puede resolver la pregunta, [incluyendo una explicación] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) realmente ayuda a mejorar la calidad de su publicación. Recuerde que usted está respondiendo la pregunta a los lectores en el futuro, y es posible que esas personas no sepan los motivos de su sugerencia de código. Por favor, intente no saturar su código con comentarios explicativos, ¡esto reduce la legibilidad tanto del código como de las explicaciones! – Carpetsmoker

0

Creo que en su caso no se necesita realmente una agrupar por. Me ordenar por orden descendente de su columna B, a continuación, colocar duplicados en la columna A y si lo desea, también puede tener una nueva agradable y índice limpia así:

df.sort_values('B', ascending=False).drop_duplicates('A').sort_index().reset_index(drop=True) 
+0

¿cómo es esto diferente a otras publicaciones? – DJK

Cuestiones relacionadas