Skip to content

BUG: clean_fill_method failing to raise #53620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/whatsnew/v2.1.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ Other
- Bug in :meth:`Series.map` when giving a callable to an empty series, the returned series had ``object`` dtype. It now keeps the original dtype (:issue:`52384`)
- Bug in :meth:`Series.memory_usage` when ``deep=True`` throw an error with Series of objects and the returned value is incorrect, as it does not take into account GC corrections (:issue:`51858`)
- Fixed incorrect ``__name__`` attribute of ``pandas._libs.json`` (:issue:`52898`)
- Bug in :meth:`Series.align`, :meth:`DataFrame.align`, :meth:`Series.reindex`, :meth:`DataFrame.reindex`,:meth:`Series.interpolate`, :meth:`DataFrame.interpolate`, incorrectly failing to raise with method="asfreq" (:issue:`??`)

.. ***DO NOT USE THIS SECTION***

Expand Down
4 changes: 3 additions & 1 deletion pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -9735,7 +9735,9 @@ def align(
method = None
if limit is lib.no_default:
limit = None
method = clean_fill_method(method)

if method is not None:
method = clean_fill_method(method)

if broadcast_axis is not lib.no_default:
# GH#51856
Expand Down
6 changes: 6 additions & 0 deletions pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1369,6 +1369,12 @@ def interpolate(
m = missing.clean_fill_method(method)
except ValueError:
m = None
# error: Non-overlapping equality check (left operand type:
# "Literal['backfill', 'bfill', 'ffill', 'pad']", right
# operand type: "Literal['asfreq']")
if method == "asfreq": # type: ignore[comparison-overlap]
# clean_fill_method used to allow this
raise
if m is None and self.dtype.kind != "f":
# only deal with floats
# bc we already checked that can_hold_na, we don't have int dtype here
Expand Down
8 changes: 3 additions & 5 deletions pandas/core/missing.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,7 @@ def mask_missing(arr: ArrayLike, values_to_mask) -> npt.NDArray[np.bool_]:
return mask


def clean_fill_method(method: str | None, allow_nearest: bool = False):
# asfreq is compat for resampling
if method in [None, "asfreq"]:
return None

def clean_fill_method(method: str, allow_nearest: bool = False):
if isinstance(method, str):
method = method.lower()
if method == "ffill":
Expand Down Expand Up @@ -954,6 +950,8 @@ def get_fill_func(method, ndim: int = 1):


def clean_reindex_fill_method(method) -> ReindexMethod | None:
if method is None:
return None
return clean_fill_method(method, allow_nearest=True)


Expand Down
4 changes: 4 additions & 0 deletions pandas/core/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,8 @@ def _upsample(self, method, limit: int | None = None, fill_value=None):
result = obj.copy()
result.index = res_index
else:
if method == "asfreq":
method = None
result = obj.reindex(
res_index, method=method, limit=limit, fill_value=fill_value
)
Expand Down Expand Up @@ -1624,6 +1626,8 @@ def _upsample(self, method, limit: int | None = None, fill_value=None):
memb = ax.asfreq(self.freq, how=self.convention)

# Get the fill indexer
if method == "asfreq":
method = None
indexer = memb.get_indexer(new_index, method=method, limit=limit)
new_obj = _take_new_index(
obj,
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/copy_view/test_interp_fillna.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def test_interpolate_cleaned_fill_method(using_copy_on_write):
df = DataFrame({"a": ["a", np.nan, "c"], "b": 1})
df_orig = df.copy()

result = df.interpolate(method="asfreq")
result = df.interpolate(method="linear")

if using_copy_on_write:
assert np.shares_memory(get_array(result, "a"), get_array(df, "a"))
Expand Down
8 changes: 8 additions & 0 deletions pandas/tests/frame/methods/test_align.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@


class TestDataFrameAlign:
def test_align_asfreq_method_raises(self):
df = DataFrame({"A": [1, np.nan, 2]})
msg = "Invalid fill method"
msg2 = "The 'method', 'limit', and 'fill_axis' keywords"
with pytest.raises(ValueError, match=msg):
with tm.assert_produces_warning(FutureWarning, match=msg2):
df.align(df.iloc[::-1], method="asfreq")

def test_frame_align_aware(self):
idx1 = date_range("2001", periods=5, freq="H", tz="US/Eastern")
idx2 = date_range("2001", periods=5, freq="2H", tz="US/Eastern")
Expand Down
7 changes: 7 additions & 0 deletions pandas/tests/frame/methods/test_reindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -1291,3 +1291,10 @@ def test_reindex_not_category(self, index_df, index_res, index_exp):
result = df.reindex(index=index_res)
expected = DataFrame(index=index_exp)
tm.assert_frame_equal(result, expected)

def test_invalid_method(self):
df = DataFrame({"A": [1, np.nan, 2]})

msg = "Invalid fill method"
with pytest.raises(ValueError, match=msg):
df.reindex([1, 0, 2], method="asfreq")
6 changes: 6 additions & 0 deletions pandas/tests/series/methods/test_interpolate.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,3 +821,9 @@ def test_interpolate_unsorted_index(self, ascending, expected_values):
result = ts.sort_index(ascending=ascending).interpolate(method="index")
expected = Series(data=expected_values, index=expected_values, dtype=float)
tm.assert_series_equal(result, expected)

def test_interpolate_afreq_raises(self):
ser = Series(["a", None, "b"], dtype=object)
msg = "Invalid fill method"
with pytest.raises(ValueError, match=msg):
ser.interpolate(method="asfreq")