Самый эффективный способ разбить фрейм данных, используя несколько DateTimeIndexes - PullRequest
0 голосов
/ 25 августа 2018

У меня есть фрейм данных, который содержит цены для ценной бумаги каждую минуту в течение длительного периода времени.

Я хотел бы извлечь подмножество цен, 1 в день между определенными часами.

Вот пример грубого принуждения (для краткости используется ежечасно):

dates  = pandas.date_range('20180101', '20180103', freq='H')
prices = pandas.DataFrame(index=dates, 
                          data=numpy.random.rand(len(dates)), 
                          columns=['price'])

Теперь у меня есть DateTimeIndex для часов в каждом дне, которые я хочу извлечь:

start = datetime.datetime(2018,1,1,8)
end   = datetime.datetime(2018,1,1,17)
day1  = pandas.date_range(start, end, freq='H')

start = datetime.datetime(2018,1,2,9)
end   = datetime.datetime(2018,1,2,13)
day2  = pandas.date_range(start, end, freq='H')

days = [ day1, day2 ]

Затем я могу использовать prices.index.isin с каждым из моих DateTimeIndexes, чтобы извлечь цены соответствующего дня:

daily_prices = [ prices[prices.index.isin(d)] for d in days]

Это работает, как и ожидалось:

daily_prices[0]

enter image description here

daily_prices[1]

enter image description here

Проблема заключается в том, что по мере увеличения длины каждого выделения DateTimeIndex и количествадней, когда я хочу извлечь увеличения, мое понимание списка замедляется до ползания.

Поскольку я знаю, что каждый выбор DateTimeIndex полностью включает в себя количество часов, которые он охватывает, я попытался использовать loc, и первый ипоследний элемент каждого индекса в моем понимании списка:

daily_prices = [ prices.loc[d[0]:d[-1]] for d in days]

Хотя немного быстрее, он все ещеисключительно медленный, когда количество дней очень велико

Существует ли более эффективный способ разделения кадра данных на диапазоны времени начала и окончания, как указано выше?

1 Ответ

0 голосов
/ 25 августа 2018

Если часы изо дня в день совпадают, как кажется, вы можете просто отфильтровать индекс, который должен быть довольно быстрым:

In [5]: prices.loc[prices.index.hour.isin(range(8,18))]
Out[5]:
                        price
2018-01-01 08:00:00  0.638051
2018-01-01 09:00:00  0.059258
2018-01-01 10:00:00  0.869144
2018-01-01 11:00:00  0.443970
2018-01-01 12:00:00  0.725146
2018-01-01 13:00:00  0.309600
2018-01-01 14:00:00  0.520718
2018-01-01 15:00:00  0.976284
2018-01-01 16:00:00  0.973313
2018-01-01 17:00:00  0.158488
2018-01-02 08:00:00  0.053680
2018-01-02 09:00:00  0.280477
2018-01-02 10:00:00  0.802826
2018-01-02 11:00:00  0.379837
2018-01-02 12:00:00  0.247583
....

РЕДАКТИРОВАТЬ: к вашему комментарию, работа непосредственно с индексом, а затем выполнение одного поиска в конце, все еще, вероятно, будет самой быстрой, даже если она не всегда последовательна изо дня в день. Кадры на один день в конце будут легко с группой.

Например:

df = prices.loc[[i for i in prices.index if (i.hour in range(8, 18) and i.day in range(1,10)) or (i.hour in range(2,4) and i.day in range(11,32))]] 
framelist = [frame for _, frame in df.groupby(df.index.date)]

предоставит вам список информационных фреймов с 1 днем ​​для каждого элемента списка и будет включать 8: 00-17: 00 для первых 10 дней каждого месяца и 2: 00-3: 00 для дней 11-31.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...