Pandas cuenta equivalente (distinto)

289

Estoy usando pandas como sustituto de db, ya que tengo varias bases de datos (oracle, mssql, etc.) y no puedo hacer una secuencia de comandos para un equivalente de SQL.

Tengo una tabla cargada en un DataFrame con algunas columnas:

YEARMONTH, CLIENTCODE, SIZE, .... etc etc

En SQL, 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?

Adriano Almeida
fuente
He hecho table.groupby (['YEARMONTH']) ['CLIENTCODE']. Unique () y vine con dos series indexadas por YEARMONTH y con todos los valores únicos. ¿Cómo contar la cantidad de valores en cada serie?
Adriano Almeida
Para algunos, value_countspodría ser la respuesta que está buscando: pandas.pydata.org/pandas-docs/stable/generated/…
sachinruk

Respuestas:

434

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
Dan Allan
fuente
2
¿Qué sucede si tengo varias columnas que quiero que sean únicas juntas, como en .drop_duplicates (subset = ['col1', 'col2'])?
ErnestScribbler
44
Cómo acceder a este recuento único. Como no hay nombre de columna
Tarun Khaneja
Muchas gracias, utilicé este estilo en la salida de resample. df_watch_record.resample ('M'). user.nunique () cuenta el número de usuarios únicos que han visto películas por mes.
Mehdi Kazemi
1
y ordénelos con table.groupby ('YEARMONTH'). CLIENTCODE.nunique (). sort_values ​​(ascendente = False)
wllbll
¿Es posible recuperar el identificador de grupo después nunique? Mucho que lo intentaba no puedo encontrar una manera, ya que el resultado de esta respuesta es una Series, no una DataFrame.
Josh Hansen
93

Aquí hay otro método, muy simple, digamos que el nombre del marco de datos es daaty el nombre de la columna esYEARMONTH

daat.YEARMONTH.value_counts()
StatguyUser
fuente
1
Me gusta esta respuesta ¿Cómo puedo usar este método si el nombre de mi columna tiene un '.' en ella (por ejemplo, 'ck.Class')? Gracias
55
daat ['ck.Class']. value_counts ()
StatguyUser
28
Esto no aborda la pregunta formulada.
Aaron Schumacher
66
esto cuenta el número de observaciones dentro de cada grupo, no el valor único de una columna determinada que tiene cada grupo.
Jason Goal
2
Esta es la respuesta incorrecta; ¡no refleja el DISTINCTrequisito de la pregunta! ¡Además, no incluye conteos de NaN!
Corey Levinson el
47

Curiosamente, muy a menudo len(unique())es unas pocas veces (3x-15x) más rápido que nunique().

Kh romano
fuente
11
¿Te refieres a esto? .CLIENTCODE.apply(lambda x: len(x.unique())), desde aquí
user4015990
66
@ user32185 tendrías que colocarlo en una applyllamada con una lambda. Por ejemplo, df.groupby('YEARMONTH')['CLIENTCODE'].apply(lambda x: x.unique().shape[0]).
3novak
3
La sintaxis no está completamente clara, len(df['column'].unique())no necesitaba la función lambda
mlh351
Tengo TypeError: object of type 'method' has no len()de Chen'scomentario, 3novak'sque funcionó para mí.
Jason Goal
4

Usando crosstab, esto devolverá más información quegroupby nunique

pd.crosstab(df.YEARMONTH,df.CLIENTCODE)
Out[196]: 
CLIENTCODE  1  2  3
YEARMONTH          
201301      2  1  0
201302      1  2  1

Después de un poco de modificación, produzca el resultado.

pd.crosstab(df.YEARMONTH,df.CLIENTCODE).ne(0).sum(1)
Out[197]: 
YEARMONTH
201301    2
201302    3
dtype: int64
YOBEN_S
fuente
¿Cómo puedo exportar esto como dos columnas YEARMONTHy count. ¿También puedo configurar el recuento en orden descendente?
Murtaza Haji
3

También estoy usando, nuniquepero será muy útil si tiene que usar una función de agregado 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
Gangaraju
fuente
0

Con la nueva versión de pandas, es fácil de obtener como marco de datos

unique_count = pd.groupby(['YEARMONTH'], as_index=False).agg(uniq_CLIENTCODE =('CLIENTCODE',pd.Series.count))
Vivek Ananthan
fuente
0

Aquí un enfoque para tener un recuento distinto en varias columnas. Tengamos algunos datos:

data = {'CLIENT_CODE':[1,1,2,1,2,2,3],
        'YEAR_MONTH':[201301,201301,201301,201302,201302,201302,201302],
        'PRODUCT_CODE': [100,150,220,400,50,80,100]
       }
table = pd.DataFrame(data)
table

CLIENT_CODE YEAR_MONTH  PRODUCT_CODE
0   1       201301      100
1   1       201301      150
2   2       201301      220
3   1       201302      400
4   2       201302      50
5   2       201302      80
6   3       201302      100

Ahora, enumere las columnas de interés y use groupby en una sintaxis ligeramente modificada:

columns = ['YEAR_MONTH', 'PRODUCT_CODE']
table[columns].groupby(table['CLIENT_CODE']).nunique()

Obtenemos:

YEAR_MONTH  PRODUCT_CODE CLIENT_CODE        
1           2            3
2           2            3
3           1            1
Ramon
fuente
0

Distintivo de columna junto con agregaciones en otras columnas

Para obtener el número distinto de valores para cualquier columna ( CLIENTCODEen su caso), podemos usar nunique. Podemos pasar la entrada como un diccionario en aggfunció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)
Vivek Payasi
fuente