diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 0b450fab53137..5b07fc31287e5 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -996,6 +996,8 @@ Groupby/resample/rolling - Bug in :meth:`.DataFrameGroupBy.describe` and :meth:`.SeriesGroupBy.describe` produces inconsistent results for empty datasets (:issue:`41575`) - Bug in :meth:`DataFrame.resample` reduction methods when used with ``on`` would attempt to aggregate the provided column (:issue:`47079`) - Bug in :meth:`DataFrame.groupby` and :meth:`Series.groupby` would not respect ``dropna=False`` when the input DataFrame/Series had a NaN values in a :class:`MultiIndex` (:issue:`46783`) +- Bug in :meth:`DataFrameGroupBy.resample` raises ``KeyError`` when getting the result from a key list which misses the resample key (:issue:`47362`) +- Reshaping ^^^^^^^^^ diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 0a62861cdaba7..dc436cd322a8d 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -502,11 +502,11 @@ def _apply_loffset(self, result): self.loffset = None return result - def _get_resampler_for_grouping(self, groupby): + def _get_resampler_for_grouping(self, groupby, key=None): """ Return the correct class for resampling with groupby. """ - return self._resampler_for_grouping(self, groupby=groupby) + return self._resampler_for_grouping(self, groupby=groupby, key=key) def _wrap_result(self, result): """ @@ -1132,7 +1132,7 @@ class _GroupByMixin(PandasObject): _attributes: list[str] # in practice the same as Resampler._attributes _selection: IndexLabel | None = None - def __init__(self, obj, parent=None, groupby=None, **kwargs) -> None: + def __init__(self, obj, parent=None, groupby=None, key=None, **kwargs) -> None: # reached via ._gotitem and _get_resampler_for_grouping if parent is None: @@ -1145,6 +1145,7 @@ def __init__(self, obj, parent=None, groupby=None, **kwargs) -> None: self._selection = kwargs.get("selection") self.binner = parent.binner + self.key = key self._groupby = groupby self._groupby.mutated = True @@ -1197,6 +1198,8 @@ def _gotitem(self, key, ndim, subset=None): # Try to select from a DataFrame, falling back to a Series try: + if isinstance(key, list) and self.key not in key: + key.append(self.key) groupby = self._groupby[key] except IndexError: groupby = self._groupby @@ -1511,7 +1514,7 @@ def get_resampler_for_grouping( # .resample uses 'on' similar to how .groupby uses 'key' tg = TimeGrouper(freq=rule, key=on, **kwargs) resampler = tg._get_resampler(groupby.obj, kind=kind) - return resampler._get_resampler_for_grouping(groupby=groupby) + return resampler._get_resampler_for_grouping(groupby=groupby, key=tg.key) class TimeGrouper(Grouper): diff --git a/pandas/tests/resample/test_resampler_grouper.py b/pandas/tests/resample/test_resampler_grouper.py index c54d9de009940..8aff217cca5c1 100644 --- a/pandas/tests/resample/test_resampler_grouper.py +++ b/pandas/tests/resample/test_resampler_grouper.py @@ -470,3 +470,30 @@ def test_resample_groupby_agg_object_dtype_all_nan(consolidate): index=idx, ) tm.assert_frame_equal(result, expected) + + +def test_groupby_resample_with_list_of_keys(): + # GH 47362 + df = DataFrame( + data={ + "date": date_range(start="2016-01-01", periods=8), + "group": [0, 0, 0, 0, 1, 1, 1, 1], + "val": [1, 7, 5, 2, 3, 10, 5, 1], + } + ) + result = df.groupby("group").resample("2D", on="date")[["val"]].mean() + expected = DataFrame( + data={ + "val": [4.0, 3.5, 6.5, 3.0], + }, + index=Index( + data=[ + (0, Timestamp("2016-01-01")), + (0, Timestamp("2016-01-03")), + (1, Timestamp("2016-01-05")), + (1, Timestamp("2016-01-07")), + ], + name=("group", "date"), + ), + ) + tm.assert_frame_equal(result, expected)