Как выполнить обратную повторную выборку временных рядов, например, 5 рабочих дней, начиная с последней даты данных?

#python #pandas #pandas-resample

#python #панды #pandas-повторная выборка

Вопрос:

Я хотел бы вычислить еженедельные доходы, но начиная с даты окончания в обратном направлении. Это моя первая попытка реализовать его с помощью pandas:

 import pandas as pd
import numpy as np
from pandas.tseries.offsets import BDay

index = pd.date_range(start='2020-09-13', end='2020-10-13', freq=BDay())
index_len = len(index)
dfw = pd.DataFrame(data=np.arange(start=1, stop=1 (index_len-1)*0.002, step=0.002),
                   index=index,
                   columns=['col1'])


def weekly_ret(x):
    if x.size > 0:
        print(f"range is {x.index[0]} - {x.index[-1]}")
        return (x.iloc[-1] - x.iloc[0]) / x.iloc[0]
    else:
        return np.nan


dfw = dfw.resample(rule='5B').apply(weekly_ret)
print(dfw)
 

затем я получаю следующий вывод, но это не то, что я хочу:

 range is 2020-09-14 00:00:00 - 2020-09-18 00:00:00
range is 2020-09-21 00:00:00 - 2020-09-25 00:00:00
range is 2020-09-28 00:00:00 - 2020-10-02 00:00:00
range is 2020-10-05 00:00:00 - 2020-10-09 00:00:00
range is 2020-10-12 00:00:00 - 2020-10-13 00:00:00
                col1
2020-09-14  0.008000
2020-09-21  0.007921
2020-09-28  0.007843
2020-10-05  0.007767
2020-10-12  0.001923
 

Я бы хотел, чтобы он начинался с 2020-10-13 обратного, чтобы последний диапазон был:

 range is 2020-10-07 00:00:00 - 2020-10-13 00:00:00 
 

вместо:

 range is 2020-10-12 00:00:00 - 2020-10-13 00:00:00
 

Что я пробовал до сих пор:

  1. Инвертирование фрейма данных с помощью dfw = dfw.reindex(index=dfw.index[::-1])
  2. Шаг № 1 выше плюс наличие правила -5B , это приводит к ошибке.
  3. Использование параметра origin для функции повторной выборки, но это не влияет на порядок вычислений, т.е. origin=dfw.index[-1]
  4. Шаг № 1 выше плюс вычисления на количество строк в инвертированном dfw = dfw.rolling(5).apply(weekly_ret)[::5] фрейме данных, но здесь я получаю NaN для первого (последнего) интервала, и это решение также несколько расточительно.

ОБНОВЛЕНИЕ: это будет желаемый результат; обратите внимание, что последний возврат учитывает неделю, начиная с последнего дня в индексе назад:

 range is 2020-09-16 00:00:00 - 2020-09-22 00:00:00 = 0.007968127490039847
range is 2020-09-23 00:00:00 - 2020-09-29 00:00:00 = 0.00788954635108482
range is 2020-09-30 00:00:00 - 2020-10-06 00:00:00 = 0.007812500000000007
range is 2020-10-07 00:00:00 - 2020-10-13 00:00:00 = 0.00773694390715668
                col1
2020-09-22  0.007968
2020-09-29  0.007890
2020-10-06  0.007813
2020-10-13  0.007737 i.e. (1.042 - 1.034)/1.034
 

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

1. можете ли вы опубликовать ожидаемый результат, чтобы мы могли проверить наш алгоритм

2. dfw = dfw.rolling(5,1).apply(weekly_ret)[::5] чтобы удалить NaN

Ответ №1:

Итак, что вы ищете, это привязанные смещения, то есть повторная выборка фрейма данных на еженедельной основе, начиная с того же дня недели, в который включен ваш последний индекс. В вашем случае 2020-10-13 это вторник, т. Е. Вы хотите использовать правило W-TUE . Я бы предложил использовать поисковый словарь для перевода .weekday() числа (например Tuesday == 1 ) в соответствующее правило. Затем вам нужно только применить вашу функцию к .resample() :

 rule_lookup={
    0:'W-MON',
    1:'W-TUE',
    2:'W-WED',
    3:'W-THU',
    4:'W-FRI',
    5:'W-SAT',
    6:'W-SUN'
}

# get the proper rule which ends on the last date in the index
rule = rule_lookup[dfw.index[-1].weekday()] 
print(f"=> resampling using rule: {rule}")
dfw = dfw.resample(rule=rule).apply(weekly_ret)
print(dfw)
 

дает:

 => resampling using rule: W-TUE
range is 2020-09-14 00:00:00 - 2020-09-15 00:00:00
range is 2020-09-16 00:00:00 - 2020-09-22 00:00:00
range is 2020-09-23 00:00:00 - 2020-09-29 00:00:00
range is 2020-09-30 00:00:00 - 2020-10-06 00:00:00
range is 2020-10-07 00:00:00 - 2020-10-13 00:00:00
                col1
2020-09-15  0.002000
2020-09-22  0.007968
2020-09-29  0.007890
2020-10-06  0.007813
2020-10-13  0.007737