tutorial recorrer español data python pandas dataframe group-by pandas-groupby

recorrer - pandas python tutorial español pdf



panda dataframe: cómo contar el número de 1 filas en una columna binaria? (3)

Tengo el siguiente Dataframe de pandas:

import pandas as pd import numpy as np df = pd.DataFrame({"first_column": [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0]}) >>> df first_column 0 0 1 0 2 0 3 1 4 1 5 1 6 0 7 0 8 1 9 1 10 0 11 0 12 0 13 0 14 1 15 1 16 1 17 1 18 1 19 0 20 0

first_column es una columna binaria de 0 y 1. Hay "clusters" de consecutivos, que siempre se encuentran en pares de al menos dos.

Mi objetivo es crear una columna que "cuente" el número de filas de unos por grupo:

>>> df first_column counts 0 0 0 1 0 0 2 0 0 3 1 3 4 1 3 5 1 3 6 0 0 7 0 0 8 1 2 9 1 2 10 0 0 11 0 0 12 0 0 13 0 0 14 1 5 15 1 5 16 1 5 17 1 5 18 1 5 19 0 0 20 0 0

Esto suena como un trabajo para df.loc() , por ejemplo, df.loc[df.first_column == 1] ... algo

Simplemente no estoy seguro de cómo tener en cuenta cada "grupo" individual de unos, y cómo etiquetar cada uno de los clústeres únicos con el "recuento de filas".

¿Cómo podría uno hacer esto?


Aquí hay otro enfoque con pandas groupby, que creo que es bastante legible. Una (posible) ventaja es que no se basa en la suposición de que solo 1 y 0 están presentes en la columna.

La idea principal es crear grupos de valores consecutivos y luego simplemente calcular su longitud. También llevamos la información del valor en el grupo, por lo que podemos filtrar por ceros.

# Relevant column -> grouper needs to be 1-Dimensional col_vals = df[''first_column''] # Group by sequence of consecutive values and value in the sequence. grouped = df.groupby(((col_vals!=col_vals.shift(1)).cumsum(), col_vals)) # Get the length of consecutive values if they are different from zero, else zero df[''counts''] = grouped[''first_column''].transform(lambda group: len(group))/ .where(col_vals!=0, 0)

Así es como se ven los grupos y las claves:

for key, group in grouped: print key, group (1, 0) first_column 0 0 1 0 2 0 (2, 1) first_column 3 1 4 1 5 1 (3, 0) first_column 6 0 7 0 (4, 1) first_column 8 1 9 1 (5, 0) first_column 10 0 11 0 12 0 13 0 (6, 1) first_column 14 1 15 1 16 1 17 1 18 1 (7, 0) first_column 19 0 20 0


Aquí hay un enfoque con NumPy''s cumsum y bincount -

def cumsum_bincount(a): # Append 0 & look for a [0,1] pattern. Form a binned array based off 1s groups ids = a*(np.diff(np.r_[0,a])==1).cumsum() # Get the bincount, index into the count with ids and finally mask out 0s return a*np.bincount(ids)[ids]

Ejecución de muestra -

In [88]: df[''counts''] = cumsum_bincount(df.first_column.values) In [89]: df Out[89]: first_column counts 0 0 0 1 0 0 2 0 0 3 1 3 4 1 3 5 1 3 6 0 0 7 0 0 8 1 2 9 1 2 10 0 0 11 0 0 12 0 0 13 0 0 14 1 5 15 1 5 16 1 5 17 1 5 18 1 5 19 0 0 20 0 0

Configure los primeros 6 elems para que sean 1s y luego pruebe -

In [101]: df.first_column.values[:5] = 1 In [102]: df[''counts''] = cumsum_bincount(df.first_column.values) In [103]: df Out[103]: first_column counts 0 1 6 1 1 6 2 1 6 3 1 6 4 1 6 5 1 6 6 0 0 7 0 0 8 1 2 9 1 2 10 0 0 11 0 0 12 0 0 13 0 0 14 1 5 15 1 5 16 1 5 17 1 5 18 1 5 19 0 0 20 0 0


  • Como first_column es binario, puedo usar astype(bool) para obtener True / False
  • Si tomo el opuesto de esos y cumsum obtengo una forma práctica de agrupar los True s o 1 s
  • Luego me groupby y count con transform
  • transform difunde la agregación de count en el índice original
  • Primero uso where agrupar todos los 0 s juntos.
  • Uso where nuevamente para establecer sus conteos a 0
  • Yo uso assign para generar una copia de df con una nueva columna. Esto se debe a que no quiero golpear al df que ya tenemos. Si quiere escribir directamente a df use df[''counts''] = c

t = df.first_column.astype(bool) c = df.groupby((~t).cumsum().where(t, -1)).transform(''count'').where(t, 0) df.assign(counts=c) first_column counts 0 0 0 1 0 0 2 0 0 3 1 3 4 1 3 5 1 3 6 0 0 7 0 0 8 1 2 9 1 2 10 0 0 11 0 0 12 0 0 13 0 0 14 1 5 15 1 5 16 1 5 17 1 5 18 1 5 19 0 0 20 0 0