dave
Digamos que tengo un registro de la actividad de los usuarios y quiero generar un informe de la duración total y la cantidad de usuarios únicos por día.
import numpy as np
import pandas as pd
df = pd.DataFrame({'date': ['2013-04-01','2013-04-01','2013-04-01','2013-04-02', '2013-04-02'],
'user_id': ['0001', '0001', '0002', '0002', '0002'],
'duration': [30, 15, 20, 15, 30]})
Agregar la duración es bastante sencillo:
group = df.groupby('date')
agg = group.aggregate({'duration': np.sum})
agg
duration
date
2013-04-01 65
2013-04-02 45
Lo que me gustaría hacer es sumar la duración y contar los distintivos al mismo tiempo, pero parece que no puedo encontrar un equivalente para count_distinct:
agg = group.aggregate({ 'duration': np.sum, 'user_id': count_distinct})
Esto funciona, pero seguramente hay una mejor manera, ¿no?
group = df.groupby('date')
agg = group.aggregate({'duration': np.sum})
agg['uv'] = df.groupby('date').user_id.nunique()
agg
duration uv
date
2013-04-01 65 2
2013-04-02 45 1
Estoy pensando que solo necesito proporcionar una función que devuelva el recuento de elementos distintos de un objeto Serie a la función agregada, pero no tengo mucha exposición a las diversas bibliotecas a mi disposición. Además, parece que el objeto groupby ya conoce esta información, así que ¿no estaría simplemente duplicando el esfuerzo?
¿Qué tal cualquiera de:
>>> df
date duration user_id
0 2013-04-01 30 0001
1 2013-04-01 15 0001
2 2013-04-01 20 0002
3 2013-04-02 15 0002
4 2013-04-02 30 0002
>>> df.groupby("date").agg({"duration": np.sum, "user_id": pd.Series.nunique})
duration user_id
date
2013-04-01 65 2
2013-04-02 45 1
>>> df.groupby("date").agg({"duration": np.sum, "user_id": lambda x: x.nunique()})
duration user_id
date
2013-04-01 65 2
2013-04-02 45 1
-
Eso es todo. pd.Series.nunique es lo que no pude encontrar, bueno, no pude hacer que funcionara correctamente. Bastante obvio en retrospectiva. ¡Gracias!
– dave
1 de septiembre de 2013 a las 3:36
-
Esta respuesta está desactualizada. Ahora puedes usar
nunique
directamente. Vea la solución de @Blodwyn Pig a continuación–Ted Petrou
5 de noviembre de 2017 a las 20:07
-
Oye, ¿sabes cómo obtener un recuento no duplicado?
– haneulkim
25 de febrero de 2020 a las 4:17
Ricky McMaster
‘nunique’ es una opción para .agg() desde pandas 0.20.0, entonces:
df.groupby('date').agg({'duration': 'sum', 'user_id': 'nunique'})
-
¿Es posible agregar y obtener los valores únicos? algo como
duration: np.unique
– tipo
26/09/2017 a las 20:31
-
@chico Prueba
df.groupby('date').agg({'user_id': lambda s: s.unique().reset_index(drop=True)})
– BolígrafoBen
14 de agosto de 2018 a las 19:01
-
¿Cómo obtenemos la salida?
– usuario9366862
15/10/2018 a las 21:09
usuario6903745
Solo agregando a las respuestas ya dadas, la solución usando la cadena "nunique"
parece mucho más rápido, probado aquí en un marco de datos de ~ 21 millones de filas, luego agrupado en ~ 2 millones
%time _=g.agg({"id": lambda x: x.nunique()})
CPU times: user 3min 3s, sys: 2.94 s, total: 3min 6s
Wall time: 3min 20s
%time _=g.agg({"id": pd.Series.nunique})
CPU times: user 3min 2s, sys: 2.44 s, total: 3min 4s
Wall time: 3min 18s
%time _=g.agg({"id": "nunique"})
CPU times: user 14 s, sys: 4.76 s, total: 18.8 s
Wall time: 24.4 s
-
¡Buena atrapada! Supongo que es b/c en un caso de “lambda”/”otra función”, se aplica secuencialmente, mientras que las funciones “conocidas” se aplican a toda la columna de forma vectorizada.
– ovnis
9 dic 2017 a las 20:16
-
¿Qué solución es de @Blodwyn Pig?
– Chogg
30 de marzo de 2018 a las 19:26
-
@Chogg, ¡el más rápido!
– mdz
23 de abril de 2018 a las 14:11
-
@Chogg: lo siento, cambié mi nombre de usuario. Fui yo.
–Ricky McMaster
16 de octubre de 2018 a las 7:49
Si desea obtener solo una cantidad de valores distintos por grupo, puede usar el método nunique
directamente con el DataFrameGroupBy
objeto:
df.groupby('date')['user_id'].nunique()