diff --git a/doc/source/groupby.rst b/doc/source/groupby.rst index 45e449d081fb0..00f2735f76552 100644 --- a/doc/source/groupby.rst +++ b/doc/source/groupby.rst @@ -389,7 +389,7 @@ This is mainly syntactic sugar for the alternative and much more verbose: Additionally this method avoids recomputing the internal grouping information derived from the passed key. -.. _groupby.iterating: +.. _groupby.iterating-label: Iterating through groups ------------------------ @@ -415,8 +415,7 @@ In the case of grouping by multiple keys, the group name will be a tuple: ...: print(group) ...: -It's standard Python-fu but remember you can unpack the tuple in the for loop -statement if you wish: ``for (k1, k2), group in grouped:``. +See :ref:`timeseries.iterating-label`. Selecting a group ----------------- diff --git a/doc/source/timeseries.rst b/doc/source/timeseries.rst index b7771436f8e55..a287557297cc9 100644 --- a/doc/source/timeseries.rst +++ b/doc/source/timeseries.rst @@ -703,6 +703,24 @@ regularity will result in a ``DatetimeIndex``, although frequency is lost: ts2[[0, 2, 6]].index +.. _timeseries.iterating-label: + +Iterating through groups +------------------------ + +With the :ref:`Resampler` object in hand, iterating through the grouped data is very +natural and functions similarly to :py:func:`itertools.groupby`: + +.. ipython:: python + + resampled = df.resample('H') + + for name, group in resampled: + print(name) + print(group) + +See :ref:`groupby.iterating-label`. + .. _timeseries.components: Time/Date Components diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 9b70bda82e247..40f9aa947eced 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -182,6 +182,7 @@ Other Enhancements - :func:`to_timedelta` now supports iso-formated timedelta strings (:issue:`21877`) - :class:`Series` and :class:`DataFrame` now support :class:`Iterable` in constructor (:issue:`2193`) - :class:`DatetimeIndex` gained :attr:`DatetimeIndex.timetz` attribute. Returns local time with timezone information. (:issue:`21358`) +- :class:`Resampler` now is iterable like :class:`GroupBy` (:issue:`15314`). .. _whatsnew_0240.api_breaking: diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 4a3625b2d7a2d..b9194443c3033 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -97,6 +97,23 @@ def __getattr__(self, attr): return object.__getattribute__(self, attr) + def __iter__(self): + """ + Resampler iterator + + Returns + ------- + Generator yielding sequence of (name, subsetted object) + for each group + + See Also + -------- + GroupBy.__iter__ + + """ + self._set_binner() + return super(Resampler, self).__iter__() + @property def obj(self): return self.groupby.obj diff --git a/pandas/tests/test_resample.py b/pandas/tests/test_resample.py index d11077668359b..48b37e5da62ae 100644 --- a/pandas/tests/test_resample.py +++ b/pandas/tests/test_resample.py @@ -771,6 +771,17 @@ def test_apply_to_empty_series(self): assert_series_equal(result, expected, check_dtype=False) + def test_resampler_is_iterable(self): + # GH 15314 + series = self.create_series() + freq = 'H' + tg = TimeGrouper(freq, convention='start') + grouped = series.groupby(tg) + resampled = series.resample(freq) + for (rk, rv), (gk, gv) in zip(resampled, grouped): + assert rk == gk + assert_series_equal(rv, gv) + class TestDatetimeIndex(Base): _index_factory = lambda x: date_range