From 125902ac6892a06b9f7801388cb7739ccbeedb97 Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 24 Jul 2023 13:46:44 -0700 Subject: [PATCH 1/2] ENH: Support ffill/bfill on IntervalArray --- doc/source/whatsnew/v2.1.0.rst | 1 + pandas/core/arrays/interval.py | 4 +--- pandas/core/arrays/sparse/array.py | 17 +--------------- pandas/tests/extension/test_interval.py | 26 ------------------------- pandas/tests/extension/test_sparse.py | 12 +----------- 5 files changed, 4 insertions(+), 56 deletions(-) diff --git a/doc/source/whatsnew/v2.1.0.rst b/doc/source/whatsnew/v2.1.0.rst index 65f5328189eeb..d9992b560ce30 100644 --- a/doc/source/whatsnew/v2.1.0.rst +++ b/doc/source/whatsnew/v2.1.0.rst @@ -132,6 +132,7 @@ to ``na_action=None``, like for all the other array types. Other enhancements ^^^^^^^^^^^^^^^^^^ +- :meth:`Series.ffill` and :meth:`Series.bfill` are now supported for objects with :class:`IntervalDtype` (:issue:`??`) - :meth:`Categorical.map` and :meth:`CategoricalIndex.map` now have a ``na_action`` parameter. :meth:`Categorical.map` implicitly had a default value of ``"ignore"`` for ``na_action``. This has formally been deprecated and will be changed to ``None`` in the future. Also notice that :meth:`Series.map` has default ``na_action=None`` and calls to series with categorical data will now use ``na_action=None`` unless explicitly set otherwise (:issue:`44279`) diff --git a/pandas/core/arrays/interval.py b/pandas/core/arrays/interval.py index 7c0263660ef55..fad866374a9b1 100644 --- a/pandas/core/arrays/interval.py +++ b/pandas/core/arrays/interval.py @@ -917,9 +917,7 @@ def fillna(self, value=None, method=None, limit: int | None = None) -> Self: filled : IntervalArray with NA/NaN filled """ if method is not None: - raise TypeError("Filling by method is not supported for IntervalArray.") - if limit is not None: - raise TypeError("limit is not supported for IntervalArray.") + return super().fillna(value=value, method=method, limit=limit) value_left, value_right = self._validate_scalar(value) diff --git a/pandas/core/arrays/sparse/array.py b/pandas/core/arrays/sparse/array.py index 18eef6faf88bf..40079f8d7ff55 100644 --- a/pandas/core/arrays/sparse/array.py +++ b/pandas/core/arrays/sparse/array.py @@ -78,7 +78,6 @@ check_array_indexer, unpack_tuple_and_ellipses, ) -from pandas.core.missing import pad_or_backfill_inplace from pandas.core.nanops import check_below_min_count from pandas.io.formats import printing @@ -757,21 +756,7 @@ def fillna( raise ValueError("Must specify one of 'method' or 'value'.") if method is not None: - msg = "fillna with 'method' requires high memory usage." - warnings.warn( - msg, - PerformanceWarning, - stacklevel=find_stack_level(), - ) - new_values = np.asarray(self) - # pad_or_backfill_inplace modifies new_values inplace - # error: Argument "method" to "pad_or_backfill_inplace" has incompatible - # type "Literal['backfill', 'bfill', 'ffill', 'pad']"; expected - # "Literal['pad', 'backfill']" - pad_or_backfill_inplace( - new_values, method=method, limit=limit # type: ignore[arg-type] - ) - return type(self)(new_values, fill_value=self.fill_value) + return super().fillna(method=method, limit=limit) else: new_values = np.where(isna(self.sp_values), value, self.sp_values) diff --git a/pandas/tests/extension/test_interval.py b/pandas/tests/extension/test_interval.py index 0f916cea9d518..487fac03d3fb8 100644 --- a/pandas/tests/extension/test_interval.py +++ b/pandas/tests/extension/test_interval.py @@ -134,32 +134,6 @@ def test_fillna_length_mismatch(self, data_missing): class TestMissing(BaseInterval, base.BaseMissingTests): - # Index.fillna only accepts scalar `value`, so we have to xfail all - # non-scalar fill tests. - unsupported_fill = pytest.mark.xfail( - reason="Unsupported fillna option for Interval." - ) - - @unsupported_fill - def test_fillna_limit_pad(self): - super().test_fillna_limit_pad() - - @unsupported_fill - def test_fillna_series_method(self): - super().test_fillna_series_method() - - @unsupported_fill - def test_fillna_limit_backfill(self): - super().test_fillna_limit_backfill() - - @unsupported_fill - def test_fillna_no_op_returns_copy(self): - super().test_fillna_no_op_returns_copy() - - @unsupported_fill - def test_fillna_series(self): - super().test_fillna_series() - def test_fillna_non_scalar_raises(self, data_missing): msg = "can only insert Interval objects and NA into an IntervalArray" with pytest.raises(TypeError, match=msg): diff --git a/pandas/tests/extension/test_sparse.py b/pandas/tests/extension/test_sparse.py index d8bab71b76df4..c22e55952e40d 100644 --- a/pandas/tests/extension/test_sparse.py +++ b/pandas/tests/extension/test_sparse.py @@ -223,11 +223,6 @@ def test_isna(self, data_missing): expected = SparseArray([False, False], fill_value=False, dtype=expected_dtype) self.assert_equal(sarr.isna(), expected) - def test_fillna_limit_pad(self, data_missing): - warns = (PerformanceWarning, FutureWarning) - with tm.assert_produces_warning(warns, check_stacklevel=False): - super().test_fillna_limit_pad(data_missing) - def test_fillna_limit_backfill(self, data_missing): warns = (PerformanceWarning, FutureWarning) with tm.assert_produces_warning(warns, check_stacklevel=False): @@ -238,12 +233,7 @@ def test_fillna_no_op_returns_copy(self, data, request): request.node.add_marker( pytest.mark.xfail(reason="returns array with different fill value") ) - with tm.assert_produces_warning(PerformanceWarning, check_stacklevel=False): - super().test_fillna_no_op_returns_copy(data) - - def test_fillna_series_method(self, data_missing, fillna_method): - with tm.assert_produces_warning(PerformanceWarning, check_stacklevel=False): - super().test_fillna_series_method(data_missing, fillna_method) + super().test_fillna_no_op_returns_copy(data) @pytest.mark.xfail(reason="Unsupported") def test_fillna_series(self): From e24e238be83bfb2192cf26bcba7cbdc0ff51873e Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 24 Jul 2023 13:48:10 -0700 Subject: [PATCH 2/2] gh ref --- doc/source/whatsnew/v2.1.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v2.1.0.rst b/doc/source/whatsnew/v2.1.0.rst index d9992b560ce30..61118c6ed3302 100644 --- a/doc/source/whatsnew/v2.1.0.rst +++ b/doc/source/whatsnew/v2.1.0.rst @@ -132,7 +132,7 @@ to ``na_action=None``, like for all the other array types. Other enhancements ^^^^^^^^^^^^^^^^^^ -- :meth:`Series.ffill` and :meth:`Series.bfill` are now supported for objects with :class:`IntervalDtype` (:issue:`??`) +- :meth:`Series.ffill` and :meth:`Series.bfill` are now supported for objects with :class:`IntervalDtype` (:issue:`54247`) - :meth:`Categorical.map` and :meth:`CategoricalIndex.map` now have a ``na_action`` parameter. :meth:`Categorical.map` implicitly had a default value of ``"ignore"`` for ``na_action``. This has formally been deprecated and will be changed to ``None`` in the future. Also notice that :meth:`Series.map` has default ``na_action=None`` and calls to series with categorical data will now use ``na_action=None`` unless explicitly set otherwise (:issue:`44279`)