Skip to content

Commit

Permalink
EHN: Implement method argument for DataFrame.replace
Browse files Browse the repository at this point in the history
  • Loading branch information
reidy-p committed Feb 25, 2018
1 parent 10cc8f4 commit 93036f8
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 6 deletions.
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.23.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ Other Enhancements
- Added :func:`SeriesGroupBy.is_monotonic_increasing` and :func:`SeriesGroupBy.is_monotonic_decreasing` (:issue:`17015`)
- For subclassed ``DataFrames``, :func:`DataFrame.apply` will now preserve the ``Series`` subclass (if defined) when passing the data to the applied function (:issue:`19822`)
- :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`)

- :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`)

.. _whatsnew_0230.api_breaking:

Expand Down
6 changes: 5 additions & 1 deletion pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4880,7 +4880,7 @@ def bfill(self, axis=None, inplace=False, limit=None, downcast=None):
``to_replace`` must be ``None``.
method : string, optional, {'pad', 'ffill', 'bfill'}
The method to use when for replacement, when ``to_replace`` is a
``list``.
scalar, list or tuple and ``value`` is None.
See Also
--------
Expand Down Expand Up @@ -5049,6 +5049,10 @@ def replace(self, to_replace=None, value=None, inplace=False, limit=None,
to_replace = [to_replace]

if isinstance(to_replace, (tuple, list)):
if isinstance(self, pd.DataFrame):
return self.apply(_single_replace,
args=(to_replace, method, inplace,
limit))
return _single_replace(self, to_replace, method, inplace,
limit)

Expand Down
37 changes: 33 additions & 4 deletions pandas/tests/frame/test_replace.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ def test_replace_inplace(self):
tsframe.replace(nan, 0, inplace=True)
assert_frame_equal(tsframe, self.tsframe.fillna(0))

pytest.raises(TypeError, self.tsframe.replace, nan, inplace=True)
pytest.raises(TypeError, self.tsframe.replace, nan)

# mixed type
mf = self.mixed_frame
mf.iloc[5:20, mf.columns.get_loc('foo')] = nan
Expand Down Expand Up @@ -720,7 +717,6 @@ def test_replace_simple_nested_dict_with_nonexistent_value(self):
assert_frame_equal(expected, result)

def test_replace_value_is_none(self):
pytest.raises(TypeError, self.tsframe.replace, nan)
orig_value = self.tsframe.iloc[0, 0]
orig2 = self.tsframe.iloc[1, 0]

Expand Down Expand Up @@ -1072,3 +1068,36 @@ def test_replace_with_empty_dictlike(self):

assert_frame_equal(df, df.replace({'b': {}}))
assert_frame_equal(df, df.replace(Series({'b': {}})))

@pytest.mark.parametrize("to_replace, method, expected", [
(0, 'bfill', {'A': [1, 1, 2],
'B': [5, nan, 7],
'C': ['a', 'b', 'c']}),
(nan, 'bfill', {'A': [0, 1, 2],
'B': [5.0, 7.0, 7.0],
'C': ['a', 'b', 'c']}),
('d', 'ffill', {'A': [0, 1, 2],
'B': [5, nan, 7],
'C': ['a', 'b', 'c']}),
([0, 2], 'bfill', {'A': [1, 1, 2],
'B': [5, nan, 7],
'C': ['a', 'b', 'c']}),
([1, 2], 'pad', {'A': [0, 0, 0],
'B': [5, nan, 7],
'C': ['a', 'b', 'c']}),
((1, 2), 'bfill', {'A': [0, 2, 2],
'B': [5, nan, 7],
'C': ['a', 'b', 'c']}),
(['b', 'c'], 'ffill', {'A': [0, 1, 2],
'B': [5, nan, 7],
'C': ['a', 'a', 'a']}),
])
def test_replace_method(self, to_replace, method, expected):
# GH 19632
df = DataFrame({'A': [0, 1, 2],
'B': [5, nan, 7],
'C': ['a', 'b', 'c']})

result = df.replace(to_replace=to_replace, value=None, method=method)
expected = DataFrame(expected)
assert_frame_equal(result, expected)

0 comments on commit 93036f8

Please sign in to comment.