diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index bad06329c4bfa..da2a9bdada469 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -772,6 +772,7 @@ Groupby/resample/rolling - Bug in :meth:`.DataFrameGroupBy.quantile` when ``interpolation="nearest"`` is inconsistent with :meth:`DataFrame.quantile` (:issue:`47942`) - Bug in :meth:`.Resampler.interpolate` on a :class:`DataFrame` with non-uniform sampling and/or indices not aligning with the resulting resampled index would result in wrong interpolation (:issue:`21351`) - Bug in :meth:`DataFrame.ewm` and :meth:`Series.ewm` when passed ``times`` and aggregation functions other than mean (:issue:`51695`) +- Bug in :meth:`DataFrame.resample` changing index type to :class:`MultiIndex` when the dataframe is empty and using an upsample method (:issue:`55572`) - Bug in :meth:`DataFrameGroupBy.agg` that raises ``AttributeError`` when there is dictionary input and duplicated columns, instead of returning a DataFrame with the aggregation of all duplicate columns. (:issue:`55041`) - Bug in :meth:`DataFrameGroupBy.apply` and :meth:`SeriesGroupBy.apply` for empty data frame with ``group_keys=False`` still creating output index using group keys. (:issue:`60471`) - Bug in :meth:`DataFrameGroupBy.apply` that was returning a completely empty DataFrame when all return values of ``func`` were ``None`` instead of returning an empty DataFrame with the original columns and dtypes. (:issue:`57775`) diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 1cfc75ea11725..1d27687d15af0 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -507,22 +507,12 @@ def _wrap_result(self, result): """ Potentially wrap any results. """ - # GH 47705 - obj = self.obj - if ( - isinstance(result, ABCDataFrame) - and len(result) == 0 - and not isinstance(result.index, PeriodIndex) - ): - result = result.set_index( - _asfreq_compat(obj.index[:0], freq=self.freq), append=True - ) - if isinstance(result, ABCSeries) and self._selection is not None: result.name = self._selection if isinstance(result, ABCSeries) and result.empty: # When index is all NaT, result is empty but index is not + obj = self.obj result.index = _asfreq_compat(obj.index[:0], freq=self.freq) result.name = getattr(obj, "name", None) @@ -1756,6 +1746,17 @@ def func(x): return x.apply(f, *args, **kwargs) result = self._groupby.apply(func) + + # GH 47705 + if ( + isinstance(result, ABCDataFrame) + and len(result) == 0 + and not isinstance(result.index, PeriodIndex) + ): + result = result.set_index( + _asfreq_compat(self.obj.index[:0], freq=self.freq), append=True + ) + return self._wrap_result(result) _upsample = _apply diff --git a/pandas/tests/resample/test_base.py b/pandas/tests/resample/test_base.py index 0db5c0c82d4d4..eb4ba6a3fdf71 100644 --- a/pandas/tests/resample/test_base.py +++ b/pandas/tests/resample/test_base.py @@ -438,6 +438,24 @@ def test_resample_size_empty_dataframe(freq, index): tm.assert_series_equal(result, expected) +@pytest.mark.parametrize("index", [DatetimeIndex([]), TimedeltaIndex([])]) +@pytest.mark.parametrize("freq", ["D", "h"]) +@pytest.mark.parametrize( + "method", ["ffill", "bfill", "nearest", "asfreq", "interpolate", "mean"] +) +def test_resample_apply_empty_dataframe(index, freq, method): + # GH#55572 + empty_frame_dti = DataFrame(index=index) + + rs = empty_frame_dti.resample(freq) + result = rs.apply(getattr(rs, method)) + + expected_index = _asfreq_compat(empty_frame_dti.index, freq) + expected = DataFrame([], index=expected_index) + + tm.assert_frame_equal(result, expected) + + @pytest.mark.parametrize( "index", [