Фильтр значений индекса по условию
Есть датафрейм в таком виде:
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 шт):
Можно попробовать так:
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