Фильтр значений индекса по условию

Есть датафрейм в таком виде:

                      O     C     L     H
'2022-12-10 10:25:00' 25.0  26.3  24.7  27.3
'2022-12-10 10:26:00' 26.3  19.6  19.5  26.4
'2022-12-10 10:27:00' 19.6  20.5  19.4  20.8
'2022-12-10 10:28:00' 20.5  20.8  20.2  20.5
'2022-12-10 10:29:00' 23.0  25.0  22.1  25.2
'2022-12-10 10:30:00' 25.0  21.0  20.5  25.5 
'2022-12-10 10:31:00' 21.0  19.0  18.3  23.8
'2022-12-10 10:32:00' 19.0  22.0  18.1  22.7
'2022-12-10 10:33:00' 22.0  18.0  17.4  24.6
'2022-12-10 10:34:00' 18.0  23.0  15.1  25.4
'2022-12-10 10:35:00' 23.0  15.0  13.9  23.8
'2022-12-10 10:36:00' 15.0  20.0  14.0  20.5
'2022-12-10 10:37:00' 20.0  21.5  18.4  22.0

Собственно, это датафрейм цены акции, за небольшой промежуток времени. Индекс имеет тип datetime32[ns] или DatetimeIndex, остальные колонки - это цена открытия, закрытия, минимальная цена, максимальная - все стандартно.

Задача в следущем, необходимо отобрать значения цены, которая была в диапазоне каждые 5 минут, т.е., необходимы эти индексы (выделил стрелочкой):

                      O     C     L     H
'2022-12-10 10:25:00' 25.0  26.3  24.7  27.3
'2022-12-10 10:26:00' 26.3  19.6  19.5  26.4
'2022-12-10 10:27:00' 19.6  20.5  19.4  20.8
'2022-12-10 10:28:00' 20.5  20.8  20.2  20.5
'2022-12-10 10:29:00' 23.0  25.0  22.1  25.2 <-
'2022-12-10 10:30:00' 25.0  21.0  20.5  25.5 
'2022-12-10 10:31:00' 21.0  19.0  18.3  23.8
'2022-12-10 10:32:00' 19.0  22.0  18.1  22.7
'2022-12-10 10:33:00' 22.0  18.0  17.4  24.6
'2022-12-10 10:34:00' 18.0  23.0  15.1  25.4 <-
'2022-12-10 10:35:00' 23.0  15.0  13.9  23.8
'2022-12-10 10:36:00' 15.0  20.0  14.0  20.5
'2022-12-10 10:37:00' 20.0  21.5  18.4  22.0

Вроде бы все просто, бери да отбирай значения методами period, shift или просто пробежаться по колонке индекса, проверить делиться ли значение минут временного периода на 5 с остатком 4 и добавить это значение в новый датафрейм, в общем получиться результат типа такого:

                      O     C     L     H
'2022-12-10 10:29:00' 23.0  25.0  22.1  25.2
'2022-12-10 10:34:00' 18.0  23.0  15.1  25.4

Но это не верный результат, так как цена открытия, закрытия, минимальная и максимальная, должна браться не только с индекса, на 5-й минуте, но и с предыдущих 4, которые идут за ним, т.е. должно быть так:

                      O     C     L     H
'2022-12-10 10:25:00' 25.0  26.3  24.7  27.3
'2022-12-10 10:26:00' 26.3  19.6  19.5  26.4
'2022-12-10 10:27:00' 19.6  20.5  19.4  20.8
'2022-12-10 10:28:00' 20.5  20.8  20.2  20.5
'2022-12-10 10:29:00' 23.0  25.0  22.1  25.2 <-
# конечный результат должен быть таким:
'2022-12-10 10:29:00' 25.0  25.0  19.4  27.3

т.е. мы должны найти индекс и проверить, 5-я ли это минута, если да, то берем срез этого индекса и 4-ре индекса перед ним и мы должны получить из этого среза минимальное значение по колонке L, максимальное по колонке H, цена открытия должна браться с 0 индекса, в примере он выглядит так:

'2022-12-10 10:25:00' 25.0  26.3  24.7  27.3

а цена закрытия с последнего:

'2022-12-10 10:29:00' 23.0  25.0  22.1  25.2

Вопрос состоит в том, как это провернуть, т.е. нужно отфильтровать датафрейм и полученный фильтр перенести на другой, где будут только 5-ти минутные значения, учитывая, что датафрейм состоит из 1,6млн+ строк, пробежаться по индексу через функцию map, apply по условию - выходит не очень приятно по времени(. Уверен существует гениально-элегантное решение, которое уже предусмотрено самим пандосом на этот случай, какое?)


Ответы (1 шт):

Автор решения: strawdog

Можно попробовать так:

import pandas as pd
from pandas.tseries.frequencies import to_offset

res = df.resample("5T", ).agg({"O":"first", "C": "last", "L":min, "H":max})
res.index = res.index + to_offset("4T")

res:

                        O     C     L     H
2022-12-10 10:29:00  25.0  25.0  19.4  27.3
2022-12-10 10:34:00  25.0  23.0  15.1  25.5
2022-12-10 10:39:00  23.0  21.5  13.9  23.8
→ Ссылка