Tengo el siguiente código:
import pandas as pd
import random
a = [random.randint(0, 1) for i in range(30)]
b = [random.randint(0, 1) for i in range(30)]
print(a)
print(b)
df = pd.DataFrame([a, b])
df = df.T
columns = ['column1', 'column2']
df.columns = columns
print(df)
que crea un marco de datos almacenado en la variable 'df'. Consta de 2 columnas (columna1 y columna2) llenas de ceros y unos aleatorios.
Este es el resultado que obtuve cuando ejecuté el programa (si intentas ejecutarlo, no obtendrás exactamente el mismo resultado debido a la generación de randomint).
column1 column2
0 0 1
1 1 0
2 0 1
3 1 1
4 0 1
5 1 1
6 0 1
7 1 1
8 1 0
9 0 1
10 0 0
11 1 1
12 1 1
13 0 1
14 0 0
15 0 1
16 1 1
17 1 1
18 0 1
19 1 0
20 0 0
21 1 0
22 0 1
23 1 0
24 1 1
25 0 0
26 1 1
27 1 0
28 0 1
29 1 0
Me gustaría crear un filtro en la columna2, mostrando solo los grupos de datos cuando hay tres o más 1 en una fila. La salida sería algo como esto:
column1 column2
2 0 1
3 1 1
4 0 1
5 1 1
6 0 1
7 1 1
11 1 1
12 1 1
13 0 1
15 0 1
16 1 1
17 1 1
18 0 1
Dejé un espacio entre los grupos para mayor claridad visual, pero la salida real no tendría los espacios vacíos en el marco de datos.
Me gustaría hacerlo de la siguiente manera.
filter1 = (some boolean condition) &/| (maybe some other stuff)
final_df = df[filter1]
Gracias
Podemos usar GroupBy.transform
.
n = 3
blocks = df['column2'].ne(df['column2'].shift()).cumsum()
m1 = (df.groupby(blocks)['column2']
.transform('size').ge(n))
m2 = df['column2'].eq(1)
df_filtered = df.loc[m1 & m2]
# Alternative without df['column2'].eq(1)
#df_filtered = df.loc[m1.mul(df['column2'])]
print(df_filtered)
Producción
column1 column2
2 0 1
3 1 1
4 0 1
5 1 1
6 0 1
7 1 1
11 1 1
12 1 1
13 0 1
15 0 1
16 1 1
17 1 1
18 0 1
Si la columna2 realmente contiene solo 1 y 0 en su DataFrame original, entonces podemos usar transform('sum')
en su lugartransform('size')
bloques tiene un nuevo valor cada vez que el valor en column2
cambia
print(blocks)
0 1
1 2
2 3
3 3
4 3
5 3
6 3
7 3
8 4
9 5
10 6
11 7
12 7
13 7
14 8
15 9
16 9
17 9
18 9
19 10
20 10
21 10
22 11
23 12
24 13
25 14
26 15
27 16
28 17
29 18
Name: column2, dtype: int64
Alternativa
A menudo uso este código en mis proyectos y llegué a la conclusión de que, en general, puede ser un poco más rápido de usar Series.map
+ Series.value_counts
. La diferencia de rendimiento entre los dos métodos nunca será grande y puede elegir el que desee. Pero suelo usar este último que he explicado y creo que valió la pena mencionarlo
%%timeit
m1 = blocks.map(blocks.value_counts().ge(n))
1.41 ms ± 122 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%%timeit
m1 = (df.groupby(blocks)['column2']
.transform('size').ge(n))
2.12 ms ± 226 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.
En caso de infracción, por favor [email protected] Eliminar
Déjame decir algunas palabras