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''}