#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
Что я пробовал до сих пор:
- Инвертирование фрейма данных с помощью
dfw = dfw.reindex(index=dfw.index[::-1])
- Шаг № 1 выше плюс наличие правила
-5B
, это приводит к ошибке. - Использование параметра origin для функции повторной выборки, но это не влияет на порядок вычислений, т.е.
origin=dfw.index[-1]
- Шаг № 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