Для моего теста я использовал следующий DataFrame:
t_msec ID
0 60 0200
1 70 020a
2 445 01f4
3 555 0200
4 660 02e2
5 1005 0200
6 1510 02e2
7 2105 0200
8 2260 02e2
Так что если мы ищем, например, ID == '0200' , в пределах 1 с от начальная строка ( t_mse c == 60 ) вперед, затем есть строки 3 , на t_mse c == [60, 555, 1005] .
Чтобы вычислить весь результат, мы должны выполнить несколько трюков:
Для выполнения скользящих вычислений на основе временного ряда , мы должны вычислить временный столбец, включающий pd.to_datetime и установить его в качестве индекса.
Но скользящие вычисления выполняются в обратном направлении из текущая строка, то есть Pandas ищет строки между, например, 1 с до текущего индекса и сейчас (текущий индекс) и выполняет определенные вычисления для строк в этом окне, в то время как мы хотим, чтобы окно смотрело forward . Таким образом, здесь необходим трюк:
- вычислить индекс как df.t_mse c .max () - df.t_mse c [мс] ,
- обработайте его в обратном порядке,
- снова измените порядок результата.
Причина последнего трюка заключается в том, что:
- мы хотим взглянуть на столбец ID ( строка ),
- , но скользящие вычисления можно выполнять только для цифр c столбцы.
К счастью, столбец ID содержит только строки hex , которые можно преобразовать в INT . Поэтому мы конвертируем его и сохраняем в новом (временном) столбце.
Первым шагом является выполнение вычислений «настройки»:
lbl = int('0200', 16) # Label to look for (hex -> dec)
# ID converted to dec
df['ID_dec'] = df.ID.apply(lambda x: int(x, 16))
# Set index
df = df.set_index(pd.to_datetime(df.t_msec.max() - df.t_msec, unit='ms'))
, чтобы df содержит теперь:
t_msec ID ID_dec
t_msec
1970-01-01 00:00:02.200 60 0200 512
1970-01-01 00:00:02.190 70 020a 522
1970-01-01 00:00:01.815 445 01f4 500
1970-01-01 00:00:01.705 555 0200 512
1970-01-01 00:00:01.600 660 02e2 738
1970-01-01 00:00:01.255 1005 0200 512
1970-01-01 00:00:00.750 1510 02e2 738
1970-01-01 00:00:00.155 2105 0200 512
1970-01-01 00:00:00.000 2260 02e2 738
Второй (основной) шаг - вычисление столбца Nr :
df['Nr'] = df.ID_dec[::-1].rolling(window=pd.offsets.Second(1), closed='both')\
.apply(lambda grp: grp[grp == lbl].size, raw=False).astype(int)[::-1]
Обратите внимание на [ :: - 1] реверсирование исходного столбца и самого результата.
Now df содержит:
t_msec ID ID_dec Nr
t_msec
1970-01-01 00:00:02.200 60 0200 512 3
1970-01-01 00:00:02.190 70 020a 522 2
1970-01-01 00:00:01.815 445 01f4 500 2
1970-01-01 00:00:01.705 555 0200 512 2
1970-01-01 00:00:01.600 660 02e2 738 1
1970-01-01 00:00:01.255 1005 0200 512 1
1970-01-01 00:00:00.750 1510 02e2 738 1
1970-01-01 00:00:00.155 2105 0200 512 1
1970-01-01 00:00:00.000 2260 02e2 738 0
И последний шаг - временное удаление столбцы и восстановить исходный индекс:
df = df.drop(columns='ID_dec').reset_index(drop=True)
Окончательный результат:
t_msec ID Nr
0 60 0200 3
1 70 020a 2
2 445 01f4 2
3 555 0200 2
4 660 02e2 1
5 1005 0200 1
6 1510 02e2 1
7 2105 0200 1
8 2260 02e2 0
Время выполнения должно быть значительно короче. Напишите комментарий о времени выполнения вашего кода и моего (+ номер строки).