Este es mi Dataframe actual, archivo csv ordenado por hora de inicio de sesión y luego reset_index

    Login Time          User    Port
0   2019-10-19 22:00:05 Jane    22
1   2019-10-19 22:00:05 Jane    22
2   2019-10-19 22:02:30 John    22
3   2019-10-19 22:02:44 John    22
4   2019-10-19 22:02:54 John    22
5   2019-10-19 22:03:59 Mary    22
6   2019-10-19 22:04:12 John    22
7   2019-10-19 22:04:17 John    22
8   2019-10-19 22:04:42 Kathy   22
9   2019-10-19 22:04:42 Kathy   22

Lo que quiero es una columna separada que cuente cuántas veces el usuario ha iniciado sesión durante los últimos 30 segundos, de esta manera:

    Login Time          User    Port    LastLogin30Sec
0   2019-10-19 22:00:05 Jane    22      1
1   2019-10-19 22:00:05 Jane    22      2
2   2019-10-19 22:02:30 John    22      1
3   2019-10-19 22:02:44 John    22      2
4   2019-10-19 22:02:54 John    22      3
5   2019-10-19 22:03:59 Mary    22      1
6   2019-10-19 22:04:12 John    22      1
7   2019-10-19 22:04:17 John    22      2
8   2019-10-19 22:04:42 Kathy   22      1
9   2019-10-19 22:04:42 Kathy   22      2

Así que decidí usar el desplazamiento para especificar el período de tiempo y contar las filas. Para continuar con un período de tiempo, se debe indexar DateTime

df = df.set_index("Login Time")
df[df["User"]=="John"]["Port"].rolling("30s").count()

Login Time
2019-10-19 22:02:30    1.0
2019-10-19 22:02:44    2.0
2019-10-19 22:02:54    3.0
2019-10-19 22:04:12    1.0
2019-10-19 22:04:17    2.0
Name: Port, dtype: float64

Está bien, ese código funciona. Pero me gustaría hacer esto para cada usuario, así que decidí aprovechar groupby ... y aquí es donde se encuentra un obstáculo.

Debido a que pasar por período de tiempo necesita un índice de fecha y hora, tengo que preservar el índice en groupby. Pero el índice en no único

df["Count"] = df.groupby(["User"], as_index=False)['Port'].rolling("30s").count()
ValueError: cannot handle a non-unique multi-index!

Así que pensé, que podría no establecer el índice de tiempo en primer lugar, y establecerlo después de la operación groupby ... pero no se puede establecer_index en un framebydataframe

df["Count"] = df.groupby(["User"], as_index=False).set_index("Login Time")["Port"].rolling("30s").count()
AttributeError: Cannot access callable attribute 'set_index' of 'DataFrameGroupBy' objects, try using the 'apply' method

Y no veo cómo postularme funcionaría para mí.

¿Alguien puede aconsejar más? Todo el problema parece centrarse en la ventana de tiempo .rolling necesita un índice datetime en lugar de solo una serie datetime

0
kype 19 oct. 2019 a las 20:29

1 respuesta

La mejor respuesta

Puede usar la función de aplicación en la que puede realizar su función de desplazamiento para cada grupo

df = pd.DataFrame([[0, pd.Timestamp('2019-10-19 22:00:05'), 'Jane', '22'], [1, pd.Timestamp('2019-10-19 22:00:05'), 'Jane', '22'], [2, pd.Timestamp('2019-10-19 22:02:30'), 'John', '22'], [3, pd.Timestamp('2019-10-19 22:02:44'), 'John', '22'], [4, pd.Timestamp('2019-10-19 22:02:54'), 'John', '22'], [5, pd.Timestamp('2019-10-19 22:03:59'), 'Mary', '22'], [6, pd.Timestamp('2019-10-19 22:04:12'), 'John', '22'], [7, pd.Timestamp('2019-10-19 22:04:17'), 'John', '22'], [8, pd.Timestamp('2019-10-19 22:04:42'), 'Kathy', '22'], [9, pd.Timestamp('2019-10-19 22:04:42'), 'Kathy', '22']], columns=('id', 'Login-Time', 'User', 'Port'))

df2 = df.groupby("User").apply(lambda g: g.set_index("Login-Time")["Port"].rolling("30s").count()).reset_index()
print(df2)

Resultado

 User          Login-Time  Port
0   Jane 2019-10-19 22:00:05   1.0
1   Jane 2019-10-19 22:00:05   2.0
2   John 2019-10-19 22:02:30   1.0
3   John 2019-10-19 22:02:44   2.0
4   John 2019-10-19 22:02:54   3.0
5   John 2019-10-19 22:04:12   1.0
6   John 2019-10-19 22:04:17   2.0
7  Kathy 2019-10-19 22:04:42   1.0
8  Kathy 2019-10-19 22:04:42   2.0
9   Mary 2019-10-19 22:03:59   1.0
1
Dev Khadka 20 oct. 2019 a las 04:14