Repository: pandas-dev/pandas

Issue:
ENH: add quantile method to resample
#### Problem description

The `quantile` method is currently not supported on `resample`. While `resample(...).agg(lambda x: x.quantile(..))` works fine, it would be nice to add the `resample(..).quantile(..)` shortcut.

#### Code Sample

```
In [19]: ts = pd.Series(range(20), index=pd.date_range('2016-01-01', periods=20))

In [21]: ts.resample('W').agg(lambda x: x.quantile(0.75))
Out[21]: 
2016-01-03     1.5
2016-01-10     7.5
2016-01-17    14.5
2016-01-24    18.5
Freq: W-SUN, dtype: float64
```

So it would be nice the following would give the same result:
```
In [22]: ts.resample('W').quantile(0.75)
/home/joris/miniconda3/envs/dev/bin/ipython:1: FutureWarning: 
.resample() is now a deferred operation
You called quantile(...) on this deferred object which materialized it into a series
by implicitly taking the mean.  Use .resample(...).mean() instead
  #!/home/joris/miniconda3/envs/dev/bin/python
Out[22]: 14.25
```

The fact that this currently implicitly takes the mean before calculating the quantile (`ts.resample('W').mean().quantile(0.75)`) would make this change slightly API breaking.


Using pandas master, 0.19.0+289.g1bf94c8



Discussion:
BTW, using grouby this also works (and on `rolling` works as well):

```
In [23]: ts.groupby(pd.Grouper(freq='W')).quantile(0.75)
Out[23]: 
2016-01-03     1.5
2016-01-10     7.5
2016-01-17    14.5
2016-01-24    18.5
Freq: W-SUN, dtype: float64
```

In general should maybe check whether there are also other methods not working on resample.
yeah, we have specificially defined Resampler methods (as we do for groupby). 
I am taking it
@jreback can you remember if there was a specific reason that `quantile` was left out? or just an oversight?
IIRC, *some* methods (e.g. cython defined ones, and some others), are specifically defined in ``.groupby``, so these are 'named' methods and were transfered to ``.resample``. However other methods are dispatched (IOW, on the whitelist but not defined as above). I don't think I audited all of these for suitability.

So in theory, we should evaluate these and define if appropriate (or possibly make a general method to make these definitions).

Resolving patch:
diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py
--- a/pandas/core/groupby/groupby.py
+++ b/pandas/core/groupby/groupby.py
@@ -1168,7 +1168,12 @@ def var(self, ddof=1, *args, **kwargs):
         """
         nv.validate_groupby_func('var', args, kwargs)
         if ddof == 1:
-            return self._cython_agg_general('var', **kwargs)
+            try:
+                return self._cython_agg_general('var', **kwargs)
+            except Exception:
+                f = lambda x: x.var(ddof=ddof, **kwargs)
+                with _group_selection_context(self):
+                    return self._python_agg_general(f)
         else:
             f = lambda x: x.var(ddof=ddof, **kwargs)
             with _group_selection_context(self):
diff --git a/pandas/core/resample.py b/pandas/core/resample.py
--- a/pandas/core/resample.py
+++ b/pandas/core/resample.py
@@ -766,6 +766,24 @@ def size(self):
             result = pd.Series([], index=result.index, dtype='int64')
         return result
 
+    def quantile(self, q=0.5, **kwargs):
+        """
+        Return value at the given quantile.
+
+        .. versionadded:: 0.24.0
+
+        Parameters
+        ----------
+        q : float or array-like, default 0.5 (50% quantile)
+
+        See Also
+        --------
+        Series.quantile
+        DataFrame.quantile
+        DataFrameGroupBy.quantile
+        """
+        return self._downsample('quantile', q=q, **kwargs)
+
 
 # downsample methods
 for method in ['sum', 'prod']:
@@ -1060,7 +1078,8 @@ def _downsample(self, how, **kwargs):
 
         if is_subperiod(ax.freq, self.freq):
             # Downsampling
-            return self._groupby_and_aggregate(how, grouper=self.grouper)
+            return self._groupby_and_aggregate(how, grouper=self.grouper,
+                                               **kwargs)
         elif is_superperiod(ax.freq, self.freq):
             if how == 'ohlc':
                 # GH #13083


Test patch:
diff --git a/pandas/tests/test_resample.py b/pandas/tests/test_resample.py
--- a/pandas/tests/test_resample.py
+++ b/pandas/tests/test_resample.py
@@ -41,7 +41,7 @@
 
 # The various methods we support
 downsample_methods = ['min', 'max', 'first', 'last', 'sum', 'mean', 'sem',
-                      'median', 'prod', 'var', 'ohlc']
+                      'median', 'prod', 'var', 'ohlc', 'quantile']
 upsample_methods = ['count', 'size']
 series_methods = ['nunique']
 resample_methods = downsample_methods + upsample_methods + series_methods
@@ -782,6 +782,15 @@ def test_resampler_is_iterable(self):
             assert rk == gk
             assert_series_equal(rv, gv)
 
+    def test_resample_quantile(self):
+        # GH 15023
+        s = self.create_series()
+        q = 0.75
+        freq = 'H'
+        result = s.resample(freq).quantile(q)
+        expected = s.resample(freq).agg(lambda x: x.quantile(q))
+        tm.assert_series_equal(result, expected)
+
 
 class TestDatetimeIndex(Base):
     _index_factory = lambda x: date_range