Skip to content

Commit ebf9668

Browse files
authored
API: replace() should raise an exception if invalid argument is given (#31946)
1 parent 94fdc30 commit ebf9668

File tree

4 files changed

+38
-0
lines changed

4 files changed

+38
-0
lines changed

doc/source/whatsnew/v1.1.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ Reshaping
326326
- Bug in :func:`crosstab` when inputs are two Series and have tuple names, the output will keep dummy MultiIndex as columns. (:issue:`18321`)
327327
- :meth:`DataFrame.pivot` can now take lists for ``index`` and ``columns`` arguments (:issue:`21425`)
328328
- Bug in :func:`concat` where the resulting indices are not copied when ``copy=True`` (:issue:`29879`)
329+
- :meth:`DataFrame.replace` and :meth:`Series.replace` will raise a ``TypeError`` if ``to_replace`` is not an expected type. Previously the ``replace`` would fail silently (:issue:`18634`)
329330

330331

331332
Sparse

pandas/core/generic.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6169,7 +6169,9 @@ def bfill(
61696169
AssertionError
61706170
* If `regex` is not a ``bool`` and `to_replace` is not
61716171
``None``.
6172+
61726173
TypeError
6174+
* If `to_replace` is not a scalar, array-like, ``dict``, or ``None``
61736175
* If `to_replace` is a ``dict`` and `value` is not a ``list``,
61746176
``dict``, ``ndarray``, or ``Series``
61756177
* If `to_replace` is ``None`` and `regex` is not compilable
@@ -6178,6 +6180,7 @@ def bfill(
61786180
* When replacing multiple ``bool`` or ``datetime64`` objects and
61796181
the arguments to `to_replace` does not match the type of the
61806182
value being replaced
6183+
61816184
ValueError
61826185
* If a ``list`` or an ``ndarray`` is passed to `to_replace` and
61836186
`value` but they are not the same length.
@@ -6373,6 +6376,18 @@ def replace(
63736376
regex=False,
63746377
method="pad",
63756378
):
6379+
if not (
6380+
is_scalar(to_replace)
6381+
or isinstance(to_replace, pd.Series)
6382+
or is_re_compilable(to_replace)
6383+
or is_list_like(to_replace)
6384+
):
6385+
raise TypeError(
6386+
"Expecting 'to_replace' to be either a scalar, array-like, "
6387+
"dict or None, got invalid type "
6388+
f"{repr(type(to_replace).__name__)}"
6389+
)
6390+
63766391
inplace = validate_bool_kwarg(inplace, "inplace")
63776392
if not is_bool(regex) and to_replace is not None:
63786393
raise AssertionError("'to_replace' must be 'None' if 'regex' is not a bool")

pandas/tests/frame/methods/test_replace.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,3 +1363,14 @@ def test_replace_after_convert_dtypes(self):
13631363
result = df.replace(1, 10)
13641364
expected = pd.DataFrame({"grp": [10, 2, 3, 4, 5]}, dtype="Int64")
13651365
tm.assert_frame_equal(result, expected)
1366+
1367+
def test_replace_invalid_to_replace(self):
1368+
# GH 18634
1369+
# API: replace() should raise an exception if invalid argument is given
1370+
df = pd.DataFrame({"one": ["a", "b ", "c"], "two": ["d ", "e ", "f "]})
1371+
msg = (
1372+
r"Expecting 'to_replace' to be either a scalar, array-like, "
1373+
r"dict or None, got invalid type.*"
1374+
)
1375+
with pytest.raises(TypeError, match=msg):
1376+
df.replace(lambda x: x.strip())

pandas/tests/series/methods/test_replace.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,3 +362,14 @@ def test_replace_no_cast(self, ser, exp):
362362
expected = pd.Series(exp)
363363

364364
tm.assert_series_equal(result, expected)
365+
366+
def test_replace_invalid_to_replace(self):
367+
# GH 18634
368+
# API: replace() should raise an exception if invalid argument is given
369+
series = pd.Series(["a", "b", "c "])
370+
msg = (
371+
r"Expecting 'to_replace' to be either a scalar, array-like, "
372+
r"dict or None, got invalid type.*"
373+
)
374+
with pytest.raises(TypeError, match=msg):
375+
series.replace(lambda x: x.strip())

0 commit comments

Comments
 (0)