I'd like to resample a pandas object using a specific date (or month) as the edge of the first bin. For instance, in the following snippet I'd like my first index value to be 2020-02-29
and I'd be happy specifying start=2
or start="2020-02-29"
.
>>> dates = pd.date_range("2020-01-29", "2021-07-04")
>>> s = pd.Series(range(len(dates)), index=dates)
>>> s.resample('4M').count()
2020-01-31 3
2020-05-31 121
2020-09-30 122
2021-01-31 123
2021-05-31 120
2021-09-30 34
Freq: 4M, dtype: int64
So far this is the cleanest I can come up with uses pd.cut
and groupby
:
>>> rule = "4M"
>>> start = pd.Timestamp("2020-02-29") - pd.tseries.frequencies.to_offset(rule)
>>> end = s.index.max() + pd.tseries.frequencies.to_offset(rule)
>>> bins = pd.date_range(start, end, freq=rule)
>>> gb = s.groupby(pd.cut(s.index, bins)).count()
>>> gb.index = gb.index.categories.right
>>> gb
2020-02-29 32
2020-06-30 122
2020-10-31 123
2021-02-28 120
2021-06-30 122
2021-10-31 4
dtype: int64
pd.cut(s.index, bins, labels=bins[1:])
to group; specifying the bins in the cut saves you the step of re-defining the index. Also since the day of the date is entirely irrelevant with a '4M' offset you can remove the ambiguity by specifying only the YM for the start:pd.Timestamp("2020-02")
. Other than that your cut is pretty much the way to go. – Peerless