Repository: pandas-dev/pandas
Pull request: BUG/ENH - base argument no longer ignored in period resample
- [ ] closes #23882
- [ ] tests added / passed
- [ ] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [ ] whatsnew entry


Problem statement:
BUG: base argument ignored in PeriodIndex resample
#### Code Sample

```python
df = pd.DataFrame(np.random.randn(100, 10), index=pd.period_range('19700101', periods=100, freq='H'))
period_resample_with_base = df.resample('24H', base=10).mean().to_timestamp()
ts_resample_with_base = df.to_timestamp().resample('24H', base=10).mean()
ts_resample_no_base =  df.to_timestamp().resample('24H').mean()

period_resample_with_base.to_timestamp().equals(ts_resample_with_base)  # -> False, should be True
period_resample_with_base.to_timestamp().equals(ts_resample_no_base)  # -> True, should be False
```
#### Problem description
The base argument is ignored when resampling with PeriodIndex. It seems that the problem lies in `pandas.core.resample.TimeGrouper._get_period_bins`, where the base option should be applied (as it is in `_get_time_bins`) to get the start and end of the grouped interval.

At the very least providing the base argument to PeriodIndex resample should raise an exception.

#### Output of ``pd.show_versions()``

v0.24.0-dev

Hints from issue discussion:
That seems reasonable.  A PR would be good here.

Commit message: TST - add a couple more tests

Patch to review:
diff --git a/pandas/core/resample.py b/pandas/core/resample.py
index 125b441e5558a..7b813c222eb83 100644
--- a/pandas/core/resample.py
+++ b/pandas/core/resample.py
@@ -1519,9 +1519,24 @@ def _get_period_bins(self, ax):
 
         start = ax.min().asfreq(self.freq, how=self.convention)
         end = ax.max().asfreq(self.freq, how='end')
+        if self.base:
+            start = start.to_timestamp()
+            end = end.to_timestamp()
+
+            p_start, p_end = _get_range_edges(start,
+                                              end,
+                                              self.freq,
+                                              closed=self.closed,
+                                              base=self.base)
+            i = None if self.freq.onOffset(start) else 1
+            j = -1 if self.freq.onOffset(end) else None
+        else:
+            p_start, p_end = start, end
+            i = j = None
 
-        labels = binner = PeriodIndex(start=start, end=end,
-                                      freq=self.freq, name=ax.name)
+        labels = binner = PeriodIndex(start=p_start, end=p_end,
+                                      freq=self.freq,
+                                      name=ax.name)[slice(i, j)]
 
         i8 = memb.asi8
         freq_mult = self.freq.n
@@ -1531,6 +1546,7 @@ def _get_period_bins(self, ax):
         i8_extend = expected_bins_count - (i8[-1] - i8[0])
         rng = np.arange(i8[0], i8[-1] + i8_extend, freq_mult)
         rng += freq_mult
+        rng -= ((freq_mult - self.base) % freq_mult)
         bins = memb.searchsorted(rng, side='left')
 
         if nat_count > 0:
diff --git a/pandas/tests/resample/test_period_index.py b/pandas/tests/resample/test_period_index.py
index 99b8edd5dbbea..76b927391701d 100644
--- a/pandas/tests/resample/test_period_index.py
+++ b/pandas/tests/resample/test_period_index.py
@@ -740,3 +740,33 @@ def test_resample_with_only_nat(self):
         expected = DataFrame([], index=expected_index)
         result = frame.resample('1s').mean()
         assert_frame_equal(result, expected)
+
+    def test_resample_with_non_zero_base(self):
+        # GH 23882
+        s = pd.Series(range(100), index=pd.period_range('19910905',
+                                                        periods=100,
+                                                        freq='H'))
+        pr = s.resample('24H', base=10).mean().to_timestamp().asfreq('24H')
+        tr = s.to_timestamp().resample('24H', base=10).mean()
+        assert_series_equal(pr, tr)
+
+        s = pd.Series(range(100), index=pd.period_range('19910905',
+                                                        periods=100,
+                                                        freq='2H'))
+        pr = s.resample('24H', base=10).mean().to_timestamp().asfreq('24H')
+        tr = s.to_timestamp().resample('24H', base=10).mean()
+        assert_series_equal(pr, tr)
+
+        s = pd.Series(range(100), index=pd.period_range('19910905',
+                                                        periods=100,
+                                                        freq='Min'))
+        pr = s.resample('5Min', base=3).mean().to_timestamp()
+        tr = s.to_timestamp().resample('5Min', base=3).mean()
+        assert_series_equal(pr, tr)
+
+        s = pd.Series(range(100), index=pd.period_range('19910905',
+                                                        periods=100,
+                                                        freq='2Min'))
+        pr = s.resample('5Min', base=3).mean().to_timestamp()
+        tr = s.to_timestamp().resample('5Min', base=3).mean()
+        assert_series_equal(pr, tr)


Code review comments:
diff_hunk: @@ -740,3 +740,33 @@ def test_resample_with_only_nat(self):
         expected = DataFrame([], index=expected_index)
         result = frame.resample('1s').mean()
         assert_frame_equal(result, expected)
+
+    def test_resample_with_non_zero_base(self):
+        # GH 23882
+        s = pd.Series(range(100), index=pd.period_range('19910905',
+                                                        periods=100,
+                                                        freq='H'))
+        pr = s.resample('24H', base=10).mean().to_timestamp().asfreq('24H')
+        tr = s.to_timestamp().resample('24H', base=10).mean()
+        assert_series_equal(pr, tr)
+
+        s = pd.Series(range(100), index=pd.period_range('19910905',
+                                                        periods=100,
+                                                        freq='2H'))
+        pr = s.resample('24H', base=10).mean().to_timestamp().asfreq('24H')
+        tr = s.to_timestamp().resample('24H', base=10).mean()
+        assert_series_equal(pr, tr)
+
+        s = pd.Series(range(100), index=pd.period_range('19910905',
+                                                        periods=100,
+                                                        freq='Min'))
+        pr = s.resample('5Min', base=3).mean().to_timestamp()
+        tr = s.to_timestamp().resample('5Min', base=3).mean()
+        assert_series_equal(pr, tr)
+
+        s = pd.Series(range(100), index=pd.period_range('19910905',
+                                                        periods=100,
+                                                        freq='2Min'))
+        pr = s.resample('5Min', base=3).mean().to_timestamp()
+        tr = s.to_timestamp().resample('5Min', base=3).mean()
+        assert_series_equal(pr, tr)
path: pandas/tests/resample/test_period_index.py
text: @user1:
Break these up into multiple tests, not one giant one.

@author:
fixed