multiple groupby for examples example columns agg python pandas group-by split-apply-combine

python - groupby - pandas group by multiple columns



pandas de pitón, DF.groupby().agg(), referencia de columna en agg() (2)

En un problema concreto, digamos que tengo un DataFrame DF

word tag count 0 a S 30 1 the S 20 2 a T 60 3 an T 5 4 the T 10

Quiero encontrar, por cada "palabra", la "etiqueta" que tiene más "recuento" . Entonces, el regreso sería algo así como

word tag count 1 the S 20 2 a T 60 3 an T 5

No me importa la columna de recuento o si la orden / Índice es original o está mal. Devolver un diccionario { ''the'': ''S'' , ...} está bien.

Espero poder hacer

DF.groupby([''word'']).agg(lambda x: x[''tag''][ x[''count''].argmax() ] )

pero no funciona. No puedo acceder a la información de la columna.

Más abstractamente, ¿qué función tiene la función en agg ( función ) como su argumento ?

por cierto, es .agg () lo mismo que .aggregate ()?

Muchas gracias.


¡Aquí hay una manera simple de descubrir qué se pasa (la solución unutbu) y luego se aplica!

In [33]: def f(x): ....: print type(x) ....: print x ....: In [34]: df.groupby(''word'').apply(f) <class ''pandas.core.frame.DataFrame''> word tag count 0 a S 30 2 a T 60 <class ''pandas.core.frame.DataFrame''> word tag count 0 a S 30 2 a T 60 <class ''pandas.core.frame.DataFrame''> word tag count 3 an T 5 <class ''pandas.core.frame.DataFrame''> word tag count 1 the S 20 4 the T 10

su función solo opera (en este caso) en una subsección del cuadro con la variable agrupada todas con el mismo valor (en este cas ''palabra''), si está pasando una función, entonces tiene que lidiar con la agregación de columnas potencialmente sin cadena; las funciones estándar, como ''suma'', hacen esto por usted

Automáticamente NO agrega en las columnas de cadena

In [41]: df.groupby(''word'').sum() Out[41]: count word a 90 an 5 the 30

ESTÁS agregando en todas las columnas

In [42]: df.groupby(''word'').apply(lambda x: x.sum()) Out[42]: word tag count word a aa ST 90 an an T 5 the thethe ST 30

Puedes hacer casi cualquier cosa dentro de la función

In [43]: df.groupby(''word'').apply(lambda x: x[''count''].sum()) Out[43]: word a 90 an 5 the 30


agg es lo mismo que aggregate . Se puede llamar a las columnas (objetos de Series ) del DataFrame , una por una.

Puede usar idxmax para recopilar las etiquetas de índice de las filas con el recuento máximo:

idx = df.groupby(''word'')[''count''].idxmax() print(idx)

rendimientos

word a 2 an 3 the 1 Name: count

y luego use loc para seleccionar esas filas en las columnas de word y tag :

print(df.loc[idx, [''word'', ''tag'']])

rendimientos

word tag 2 a T 3 an T 1 the S

Tenga en cuenta que idxmax devuelve etiquetas de índice. df.loc se puede usar para seleccionar filas por etiqueta. Pero si el índice no es único, es decir, si hay filas con etiquetas de índice duplicadas, entonces df.loc seleccionará todas las filas con las etiquetas enumeradas en idx . Así que tenga cuidado de que df.index.is_unique sea True si usa idxmax con df.loc

Alternativa, podrías usar apply . apply callable de apply se pasa un sub-DataFrame que le da acceso a todas las columnas:

import pandas as pd df = pd.DataFrame({''word'':''a the a an the''.split(), ''tag'': list(''SSTTT''), ''count'': [30, 20, 60, 5, 10]}) print(df.groupby(''word'').apply(lambda subf: subf[''tag''][subf[''count''].idxmax()]))

rendimientos

word a T an T the S

El uso de idxmax y loc suele ser más rápido que apply , especialmente para los grandes marcos de datos. Usando el% timeit de IPython:

N = 10000 df = pd.DataFrame({''word'':''a the a an the''.split()*N, ''tag'': list(''SSTTT'')*N, ''count'': [30, 20, 60, 5, 10]*N}) def using_apply(df): return (df.groupby(''word'').apply(lambda subf: subf[''tag''][subf[''count''].idxmax()])) def using_idxmax_loc(df): idx = df.groupby(''word'')[''count''].idxmax() return df.loc[idx, [''word'', ''tag'']] In [22]: %timeit using_apply(df) 100 loops, best of 3: 7.68 ms per loop In [23]: %timeit using_idxmax_loc(df) 100 loops, best of 3: 5.43 ms per loop

Si quieres un diccionario que set_index las palabras con las etiquetas, entonces podrías usar set_index y to_dict así:

In [36]: df2 = df.loc[idx, [''word'', ''tag'']].set_index(''word'') In [37]: df2 Out[37]: tag word a T an T the S In [38]: df2.to_dict()[''tag''] Out[38]: {''a'': ''T'', ''an'': ''T'', ''the'': ''S''}