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 usarastype(bool)
para obtenerTrue
/False
- Si tomo el opuesto de esos y
cumsum
obtengo una forma práctica de agrupar losTrue
s o1
s - Luego me
groupby
ycount
contransform
-
transform
difunde la agregación decount
en el índice original - Primero uso
where
agrupar todos los0
s juntos. - Uso
where
nuevamente para establecer sus conteos a0
- Yo uso
assign
para generar una copia dedf
con una nueva columna. Esto se debe a que no quiero golpear aldf
que ya tenemos. Si quiere escribir directamente adf
usedf[''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