У меня есть следующие ежедневные данные:
1983-03-30 0.001224
1983-03-31 -0.003741
1983-04-04 0.005121
1983-04-05 0.009171
1983-04-06 0.006395
1983-04-07 0.009030
1983-04-08 0.006961
1983-04-11 -0.003950
1983-04-12 0.018837
1983-04-13 -0.000324
...
Я хотел бы выполнить повторную выборку с использованием частоты раз в два месяца. Итак, я делаю:
s.resample('2ME').agg('last') # Use '2M' for older versions of Pandas
Это производит следующее:
1983-03-31 -0.003741
1983-05-31 0.001987
1983-07-31 0.005657
1983-09-30 -0.007843
1983-11-30 -0.005444
1984-01-31 0.003011
1984-03-31 -0.000324
1984-05-31 0.000649
1984-07-31 -0.001447
1984-09-30 0.002705
Однако я хотел бы сгруппировать (3,4), (5,6), (7,8) и т. д., поэтому мне нужна серия, в которой есть временные метки:
1983-04-30
1983-06-31
1983-08-31
Чтобы воспроизвести это:
index = pd.date_range(start='1983-03-28', end='1984-01-01', freq='B')
s = pd.Series(data=np.random.randn(len(index)), index=index)
Как я могу передать повторную выборку в группу по четным месяцам? Или, что еще лучше, при группировке всегда использовать первые два, а не первую 1, как в приведенном выше случае — март группируется сам по себе, затем апрель и май вместе, а не группируются март и апрель вместе.
@rma Что касается предложенного вами изменения, 'ME' был добавлен в версии 2.2. См. документацию: Смещение псевдонимов
Было бы полезно, если бы вы заполнили ГСЧ, как np.random.seed(0), чтобы результат был воспроизводимым. Для справки см. Как сделать хорошие воспроизводимые примеры панд.






Вам следует использовать closed='left':
s.resample('2M', closed='left').agg('last')
Выход:
1983-04-30 2.269755
1983-06-30 0.462782
1983-08-31 0.906045
1983-10-31 -0.098453
1983-12-31 1.336528
Freq: 2M, dtype: float64
См. документацию resample:
закрыто {'право', 'лево'}, по умолчанию Нет Какая сторона интервала интервала закрыто. По умолчанию установлено значение «влево» для всех смещений частоты, кроме «ME», «YE», «QE», «BME», «BA», «BQE» и «W», которые имеют значения по умолчанию. «правильного».
Это неправильно – окончание предыдущего периода включается в следующий период!
Ответ @mozway неверен, поскольку он включает последние данные за предыдущие 2 месяца в следующие 2 месяца (например, в результаты за 30 июня он будет включать 30 апреля)! Способ сделать это таков:
np.random.seed(0)
N=365
r = pd.Series(100+np.random.randn(N), index=pd.bdate_range(start='2000-01-01', periods=N))
r = r.pct_change().dropna()
r = r.to_frame().rename(columns = {0:'r'})
r = r.reset_index().rename(columns = {'index':'date'})
r['odd_month'] = r['date'].dt.month % 2
r['grouping_date'] = r.apply(lambda x: x['date'] + DateOffset(months=x['odd_month']), axis=1).dt.strftime('%Y%m')
r['r'] +=1
r = r.groupby('grouping_date').agg({'date': 'last', 'r':'prod'}).set_index('date') - 1
r = r['r']
Выход:
date
2024-02-29 0.001835
2024-04-30 -0.007572
2024-06-28 -0.007623
2024-08-30 -0.014359
2024-10-31 0.033280
2024-12-31 -0.027050
2025-02-28 0.011792
2025-04-30 -0.005063
2025-05-23 -0.001721
Name: r, dtype: float64
Есть ли у вас возможность просто отказаться от первого месяца? Это хак, который может поставить под угрозу качество набора данных, но ваша группировка, вероятно, будет работать даже месяцы, если вы ее запустите
df.iloc[2:].resample('2M').agg('last')