Как я могу получать значения в каждый n-й час из фрейма данных Pandas?

#python #pandas #datetime

Вопрос:

Я хотел бы получать значения через каждый n-й час из фрейма данных Pandas. Фрейм данных использует столбец DateTime в качестве индекса, как это:

                                                        Value A             Value B               Value C
timestamp
2021-03-29 23:58:59.443000 00:00                           0.7                 0.2                   0.0
2021-03-29 23:58:59.458000 00:00                           0.0                 0.1                   0.1
2021-03-29 23:58:59.474000 00:00                           0.3                 0.0                   0.2
2021-03-29 23:59:59.446000 00:00                           0.2                 0.0                   0.0
2021-03-29 23:59:59.461000 00:00                           0.0                 0.0                   0.5
 

Теперь я хотел бы извлекать значения через каждый n-й час. Каков наилучший способ сделать это? Единственный способ, который я могу придумать прямо сейчас, — это создать список с датами, в которые должны быть извлечены значения, затем пройтись по этому списку, найти дату в кадре данных с наименьшей разницей и получить значения на эту дату. Но мне кажется, что это довольно плохая практика.

Комментарии:

1. Возможно, что-то вроде: df.index.dt.hour.isin([1, 3, 5, 7]) что-то в этом роде?

2. Выглядит очень многообещающе, попробую сразу!

3. Однако работает ли это с данными, охватывающими более одного дня?

4. Другое предложение, попробуйте df.asfreq , может df.asfreq("nH") быть, или повторите выборку df.resample("nH").first() , замените n числом или даже между временами в зависимости от того, что вы хотите

Ответ №1:

Используйте asof слияние. Это приведет к объединению всей строки за ближайшее время в вашем кадре данных с почасовой частотой. Вы можете изменить направление, чтобы быть ближе всего в будущем или прошлом, а не в любом из направлений.

 import pandas as pd

# Series of hours that span the range of the Index
s = pd.Series(pd.date_range(df.index.min().floor('H'), df.index.max().ceil('H'), freq='H'),
              name='times')

pd.merge_asof(s, df.reset_index(), left_on='times', right_on='timestamp', direction='nearest')
 

                       times                        timestamp  ValueA  ValueB  ValueC
0 2021-03-29 23:00:00 00:00 2021-03-29 23:58:59.443000 00:00     0.7     0.2     0.0
1 2021-03-30 00:00:00 00:00 2021-03-29 23:59:59.461000 00:00     0.0     0.0     0.5
 

Комментарии:

1. Будет ли это работать для данных, охватывающих более одного дня?

2. Зависит от того, чего ты хочешь. Если вы хотите получить ближайшее значение 2010-01-01 01:00:00, то да, это сработает. Но если вы хотите, чтобы время, ближайшее к часу 01:00:00, не зависело от даты, вы все равно можете его использовать, но вам нужно будет превратить свое время в метки времени и объединить таким образом, хотя необходимо учитывать цикличность 24 == 0.

3. Спасибо за разъяснение!