Equivalente de 'recuento (distinto)' de pandas
Estoy usando Pandas como sustituto de la base de datos porque tengo varias bases de datos ( Oracle , SQL Server , etc.) y no puedo realizar una secuencia de comandos en un equivalente de SQL.
Tengo una tabla cargada en un DataFrame con algunas columnas:
YEARMONTH, CLIENTCODE, SIZE, etc., etc.
En SQL, para contar la cantidad de clientes diferentes por año sería:
SELECT count(distinct CLIENTCODE) FROM table GROUP BY YEARMONTH;
Y el resultado sería
201301 5000
201302 13245
¿Cómo puedo hacer eso en Pandas?
Creo que esto es lo que quieres:
table.groupby('YEARMONTH').CLIENTCODE.nunique()
Ejemplo:
In [2]: table
Out[2]:
CLIENTCODE YEARMONTH
0 1 201301
1 1 201301
2 2 201301
3 1 201302
4 2 201302
5 2 201302
6 3 201302
In [3]: table.groupby('YEARMONTH').CLIENTCODE.nunique()
Out[3]:
YEARMONTH
201301 2
201302 3
Aquí tienes otro método y es mucho más sencillo. Digamos que el nombre de su marco de datos es daat
y el nombre de la columna es YEARMONTH
:
daat.YEARMONTH.value_counts()
Curiosamente, muy a menudo len(unique())
es unas cuantas veces (3x-15x) más rápido que nunique()
.
También lo estoy usando nunique
, pero será muy útil si tienes que usar una función agregada como 'min', 'max', 'count' or 'mean'
etc.
df.groupby('YEARMONTH')['CLIENTCODE'].transform('nunique') #count(distinct)
df.groupby('YEARMONTH')['CLIENTCODE'].transform('min') #min
df.groupby('YEARMONTH')['CLIENTCODE'].transform('max') #max
df.groupby('YEARMONTH')['CLIENTCODE'].transform('mean') #average
df.groupby('YEARMONTH')['CLIENTCODE'].transform('count') #count
Distinción de columna junto con agregaciones en otras columnas
Para obtener el número distinto de valores para cualquier columna ( CLIENTCODE
en su caso), podemos usar nunique
. Podemos pasar la entrada como un diccionario en agg
función, junto con agregaciones en otras columnas:
grp_df = df.groupby('YEARMONTH').agg({'CLIENTCODE': ['nunique'],
'other_col_1': ['sum', 'count']})
# to flatten the multi-level columns
grp_df.columns = ["_".join(col).strip() for col in grp_df.columns.values]
# if you wish to reset the index
grp_df.reset_index(inplace=True)