groupby for examples example columns agg python pandas filter lambda group-by

python - for - groupby examples



Pandas de Python-filas de filtro después de groupby (3)

Por ejemplo, tengo la siguiente tabla:

index,A,B 0,0,0 1,0,8 2,0,8 3,1,0 4,1,5

Después de agrupar por A :

0: index,A,B 0,0,0 1,0,8 2,0,8 1: index,A,B 3,1,5 4,1,3

Lo que necesito es dejar filas de cada grupo, donde el número en la columna B es menor que el valor máximo de todas las filas de la columna B del grupo. Bueno, tengo un problema al traducir y formular este problema al inglés, así que aquí está el ejemplo:

Valor máximo de las filas en la columna B en el grupo 0 : 8

Así que quiero soltar la fila con el índice 0 y mantener las filas con los índices 1 y 2

Valor máximo de las filas en la columna B en el grupo 1 : 5

Así que quiero soltar la fila con el índice 4 y mantener la fila con el índice 3

He intentado utilizar la función de filtro de pandas, pero el problema es que está funcionando en todas las filas del grupo a la vez:

data = <example table> grouped = data.groupby("A") filtered = grouped.filter(lambda x: x["B"] == x["B"].max())

Entonces, lo que idealmente necesito es algún filtro, que itere a través de todas las filas del grupo.

¡Gracias por la ayuda!

PD: ¿Hay también forma de eliminar solo filas en grupos y no devolver el objeto DataFrame ?


EDITAR: Acabo de aprender una manera mucho más .transform hacer esto usando el grupo .transform por método:

def get_max_rows(df): B_maxes = df.groupby(''A'').B.transform(max) return df[df.B == B_maxes]

B_maxes es una serie que se indiza de forma idéntica como el df original que contiene el valor máximo de B para cada grupo A Puede pasar muchas funciones al método de transformación. Creo que una vez que tienen salida, ya sea como un escalar o vector de la misma longitud. Incluso puede pasar algunas cadenas como nombres de funciones comunes como ''median'' . Esto es ligeramente diferente al método de Paul H porque ''A'' no será un índice en el resultado, pero puede establecerlo fácilmente después.

import numpy as np import pandas as pd df_lots_groups = pd.DataFrame(np.random.rand(30000, 3), columns = list(''BCD'') df_lots_groups[''A''] = np.random.choice(range(10000), 30000) %timeit get_max_rows(df_lots_groups) 100 loops, best of 3: 2.86 ms per loop %timeit df_lots_groups.groupby(''A'').apply(lambda df: df[ df.B == df.B.max()]) 1 loops, best of 3: 5.83 s per loop

EDITAR:

Aquí hay una abstracción que le permite seleccionar filas de grupos usando cualquier operador de comparación válido y cualquier método de groupby válido:

def get_group_rows(df, group_col, condition_col, func=max, comparison=''==''): g = df.groupby(group_col)[condition_col] condition_limit = g.transform(func) df.query(''condition_col {} @condition_limit''.format(comparison))

Entonces, por ejemplo, si quiere que todas las filas estén por encima del valor B mediano en cada grupo A al que llama

get_group_rows(df, ''A'', ''B'', ''median'', ''>'')

Algunos ejemplos:

%timeit get_group_rows(df_lots_small_groups, ''A'', ''B'', ''max'', ''=='') 100 loops, best of 3: 2.84 ms per loop %timeit get_group_rows(df_lots_small_groups, ''A'', ''B'', ''mean'', ''!='') 100 loops, best of 3: 2.97 ms per loop


Este es el otro ejemplo para: Filtrar las filas con el valor máximo después de la operación groupby utilizando idxmax () y .loc ()

In [465]: import pandas as pd In [466]: df = pd.DataFrame({ ''sp'' : [''MM1'', ''MM1'', ''MM1'', ''MM2'', ''MM2'', ''MM2''], ''mt'' : [''S1'', ''S1'', ''S3'', ''S3'', ''S4'', ''S4''], ''value'' : [3,2,5,8,10,1] }) In [467]: df Out[467]: mt sp value 0 S1 MM1 3 1 S1 MM1 2 2 S3 MM1 5 3 S3 MM2 8 4 S4 MM2 10 5 S4 MM2 1 ### Here, idxmax() finds the indices of the rows with max value within groups, ### and .loc() filters the rows using those indices : In [468]: df.loc[df.groupby(["mt"])["value"].idxmax()] Out[468]: mt sp value 0 S1 MM1 3 3 S3 MM2 8 4 S4 MM2 10


Solo necesita usar apply en el objeto groupby . Modifiqué tus datos de ejemplo para hacer esto un poco más claro:

import pandas from io import StringIO csv = StringIO("""index,A,B 0,1,0.0 1,1,3.0 2,1,6.0 3,2,0.0 4,2,5.0 5,2,7.0""") df = pandas.read_csv(csv, index_col=''index'') groups = df.groupby(by=[''A'']) print(groups.apply(lambda g: g[g[''B''] == g[''B''].max()]))

Que impresiones:

A B A index 1 2 1 6 2 4 2 7