Skip to content

Commit a875c23

Browse files
REGR: DataFrame.replace when the replacement value was explicitly None (#46404)
1 parent 2a02ddb commit a875c23

File tree

3 files changed

+22
-0
lines changed

3 files changed

+22
-0
lines changed

doc/source/whatsnew/v1.4.2.rst

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Fixed regressions
1919
- Fixed memory performance regression in :meth:`Series.fillna` when called on a :class:`DataFrame` column with ``inplace=True`` (:issue:`46149`)
2020
- Provided an alternative solution for passing custom Excel formats in :meth:`.Styler.to_excel`, which was a regression based on stricter CSS validation. Examples available in the documentation for :meth:`.Styler.format` (:issue:`46152`)
2121
- Fixed regression in :meth:`DataFrame.replace` when a replacement value was also a target for replacement (:issue:`46306`)
22+
- Fixed regression in :meth:`DataFrame.replace` when the replacement value was explicitly ``None`` when passed in a dictionary to ``to_replace`` (:issue:`45601`, :issue:`45836`)
2223
- Fixed regression when setting values with :meth:`DataFrame.loc` losing :class:`MultiIndex` names if :class:`DataFrame` was empty before (:issue:`46317`)
2324
-
2425

pandas/core/internals/blocks.py

+7
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,13 @@ def _replace_coerce(
777777
mask=mask,
778778
)
779779
else:
780+
if value is None:
781+
# gh-45601, gh-45836
782+
nb = self.astype(np.dtype(object), copy=False)
783+
if nb is self and not inplace:
784+
nb = nb.copy()
785+
putmask_inplace(nb.values, mask, value)
786+
return [nb]
780787
return self.replace(
781788
to_replace=to_replace, value=value, inplace=inplace, mask=mask
782789
)

pandas/tests/frame/methods/test_replace.py

+14
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,20 @@ def test_replace_simple_nested_dict_with_nonexistent_value(self):
661661
result = df.replace({"col": {-1: "-", 1: "a", 4: "b"}})
662662
tm.assert_frame_equal(expected, result)
663663

664+
def test_replace_NA_with_None(self):
665+
# gh-45601
666+
df = DataFrame({"value": [42, None]}).astype({"value": "Int64"})
667+
result = df.replace({pd.NA: None})
668+
expected = DataFrame({"value": [42, None]}, dtype=object)
669+
tm.assert_frame_equal(result, expected)
670+
671+
def test_replace_NAT_with_None(self):
672+
# gh-45836
673+
df = DataFrame([pd.NaT, pd.NaT])
674+
result = df.replace({pd.NaT: None, np.NaN: None})
675+
expected = DataFrame([None, None])
676+
tm.assert_frame_equal(result, expected)
677+
664678
def test_replace_value_is_none(self, datetime_frame):
665679
orig_value = datetime_frame.iloc[0, 0]
666680
orig2 = datetime_frame.iloc[1, 0]

0 commit comments

Comments
 (0)