Skip to content

Commit 18529a0

Browse files
Backport PR #46404: REGR: DataFrame.replace when the replacement value was explicitly None (#46441)
Co-authored-by: Simon Hawkins <[email protected]>
1 parent 53e5122 commit 18529a0

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
@@ -874,6 +874,13 @@ def _replace_coerce(
874874
mask=mask,
875875
)
876876
else:
877+
if value is None:
878+
# gh-45601, gh-45836
879+
nb = self.astype(np.dtype(object), copy=False)
880+
if nb is self and not inplace:
881+
nb = nb.copy()
882+
putmask_inplace(nb.values, mask, value)
883+
return [nb]
877884
return self.replace(
878885
to_replace=to_replace, value=value, inplace=inplace, mask=mask
879886
)

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)