Использование скользящих вычислений периода времени на групповом фрейме данных - PullRequest
0 голосов
/ 19 октября 2019

Это мой текущий Dataframe, CSV-файл, отсортированный по времени входа в систему, а затем 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

То, что я хочу, это отдельный столбец, подсчитывающий, сколько раз пользователь входил в систему за последние 30 секунд,как это:

    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

Поэтому я решил использовать прокрутку, чтобы указать период времени и подсчитать строки. Роллинг с периодом времени требует индексации 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

Хорошо, этот код работает. Но я хотел бы сделать это для каждого пользователя, поэтому я решил использовать групповую работу ... и вот тут-то и наткнулся на камень преткновения.

Поскольку для перехода по периоду времени нужен индекс даты-времени, мне нужносохранить индекс в группе. Но индекс в неуникальном

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

Так что я решил, что с таким же успехом я мог бы не устанавливать индекс времени на первом месте, а устанавливать его после групповой операции .... но вы не можетеset_index для groupbydataframe

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

И я не вижу, как применение будет работать для меня.

Кто-нибудь может посоветовать дальше? Кажется, что вся проблема заключается в том, что временному окну для прокрутки нужен индекс datetime, а не просто серия datetime

1 Ответ

1 голос
/ 19 октября 2019

Вы можете использовать функцию применения, в которой вы можете выполнять свою функцию прокрутки для каждой группы

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)

Результат

 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
...