Skip to content

Commit 8d462ed

Browse files
reidy-pjreback
authored andcommitted
EHN: Implement method argument for DataFrame.replace (pandas-dev#19894)
1 parent d14fae8 commit 8d462ed

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

doc/source/whatsnew/v0.23.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ Other Enhancements
338338
- For subclassed ``DataFrames``, :func:`DataFrame.apply` will now preserve the ``Series`` subclass (if defined) when passing the data to the applied function (:issue:`19822`)
339339
- :func:`DataFrame.from_dict` now accepts a ``columns`` argument that can be used to specify the column names when ``orient='index'`` is used (:issue:`18529`)
340340
- Added option ``display.html.use_mathjax`` so `MathJax <https://www.mathjax.org/>`_ can be disabled when rendering tables in ``Jupyter`` notebooks (:issue:`19856`, :issue:`19824`)
341+
- :func:`DataFrame.replace` now supports the ``method`` parameter, which can be used to specify the replacement method when ``to_replace`` is a scalar, list or tuple and ``value`` is ``None`` (:issue:`19632`)
341342
- :meth:`Timestamp.month_name`, :meth:`DatetimeIndex.month_name`, and :meth:`Series.dt.month_name` are now available (:issue:`12805`)
342343
- :meth:`Timestamp.day_name` and :meth:`DatetimeIndex.day_name` are now available to return day names with a specified locale (:issue:`12806`)
343344

pandas/core/generic.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -4886,7 +4886,10 @@ def bfill(self, axis=None, inplace=False, limit=None, downcast=None):
48864886
``to_replace`` must be ``None``.
48874887
method : string, optional, {'pad', 'ffill', 'bfill'}
48884888
The method to use when for replacement, when ``to_replace`` is a
4889-
``list``.
4889+
scalar, list or tuple and ``value`` is None.
4890+
4891+
.. versionchanged:: 0.23.0
4892+
Added to DataFrame
48904893
48914894
See Also
48924895
--------
@@ -5055,6 +5058,10 @@ def replace(self, to_replace=None, value=None, inplace=False, limit=None,
50555058
to_replace = [to_replace]
50565059

50575060
if isinstance(to_replace, (tuple, list)):
5061+
if isinstance(self, pd.DataFrame):
5062+
return self.apply(_single_replace,
5063+
args=(to_replace, method, inplace,
5064+
limit))
50585065
return _single_replace(self, to_replace, method, inplace,
50595066
limit)
50605067

pandas/tests/frame/test_replace.py

+33-4
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@ def test_replace_inplace(self):
3333
tsframe.replace(nan, 0, inplace=True)
3434
assert_frame_equal(tsframe, self.tsframe.fillna(0))
3535

36-
pytest.raises(TypeError, self.tsframe.replace, nan, inplace=True)
37-
pytest.raises(TypeError, self.tsframe.replace, nan)
38-
3936
# mixed type
4037
mf = self.mixed_frame
4138
mf.iloc[5:20, mf.columns.get_loc('foo')] = nan
@@ -720,7 +717,6 @@ def test_replace_simple_nested_dict_with_nonexistent_value(self):
720717
assert_frame_equal(expected, result)
721718

722719
def test_replace_value_is_none(self):
723-
pytest.raises(TypeError, self.tsframe.replace, nan)
724720
orig_value = self.tsframe.iloc[0, 0]
725721
orig2 = self.tsframe.iloc[1, 0]
726722

@@ -1072,3 +1068,36 @@ def test_replace_with_empty_dictlike(self):
10721068

10731069
assert_frame_equal(df, df.replace({'b': {}}))
10741070
assert_frame_equal(df, df.replace(Series({'b': {}})))
1071+
1072+
@pytest.mark.parametrize("to_replace, method, expected", [
1073+
(0, 'bfill', {'A': [1, 1, 2],
1074+
'B': [5, nan, 7],
1075+
'C': ['a', 'b', 'c']}),
1076+
(nan, 'bfill', {'A': [0, 1, 2],
1077+
'B': [5.0, 7.0, 7.0],
1078+
'C': ['a', 'b', 'c']}),
1079+
('d', 'ffill', {'A': [0, 1, 2],
1080+
'B': [5, nan, 7],
1081+
'C': ['a', 'b', 'c']}),
1082+
([0, 2], 'bfill', {'A': [1, 1, 2],
1083+
'B': [5, nan, 7],
1084+
'C': ['a', 'b', 'c']}),
1085+
([1, 2], 'pad', {'A': [0, 0, 0],
1086+
'B': [5, nan, 7],
1087+
'C': ['a', 'b', 'c']}),
1088+
((1, 2), 'bfill', {'A': [0, 2, 2],
1089+
'B': [5, nan, 7],
1090+
'C': ['a', 'b', 'c']}),
1091+
(['b', 'c'], 'ffill', {'A': [0, 1, 2],
1092+
'B': [5, nan, 7],
1093+
'C': ['a', 'a', 'a']}),
1094+
])
1095+
def test_replace_method(self, to_replace, method, expected):
1096+
# GH 19632
1097+
df = DataFrame({'A': [0, 1, 2],
1098+
'B': [5, nan, 7],
1099+
'C': ['a', 'b', 'c']})
1100+
1101+
result = df.replace(to_replace=to_replace, value=None, method=method)
1102+
expected = DataFrame(expected)
1103+
assert_frame_equal(result, expected)

0 commit comments

Comments
 (0)