Skip to content

Commit

Permalink
Fixed pct_change with 'fill_method' returning NaN instead of 0 (#19875)
Browse files Browse the repository at this point in the history
  • Loading branch information
WillAyd authored and jreback committed Feb 25, 2018
1 parent d87ca1c commit fb54f40
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 7 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.23.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,7 @@ Numeric
- Bug in :class:`Index` constructor with ``dtype='uint64'`` where int-like floats were not coerced to :class:`UInt64Index` (:issue:`18400`)
- Bug in :class:`DataFrame` flex arithmetic (e.g. ``df.add(other, fill_value=foo)``) with a ``fill_value`` other than ``None`` failed to raise ``NotImplementedError`` in corner cases where either the frame or ``other`` has length zero (:issue:`19522`)
- Multiplication and division of numeric-dtyped :class:`Index` objects with timedelta-like scalars returns ``TimedeltaIndex`` instead of raising ``TypeError`` (:issue:`19333`)
- Bug where ``NaN`` was returned instead of 0 by :func:`Series.pct_change` and :func:`DataFrame.pct_change` when ``fill_method`` is not ``None`` (provided) (:issue:`19873`)


Indexing
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -7488,7 +7488,7 @@ def pct_change(self, periods=1, fill_method='pad', limit=None, freq=None,
**kwargs)) - 1)
rs = rs.reindex_like(data)
if freq is None:
mask = isna(com._values_from_object(self))
mask = isna(com._values_from_object(data))
np.putmask(rs.values, mask, np.nan)
return rs

Expand Down
3 changes: 0 additions & 3 deletions pandas/tests/frame/test_analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -1941,12 +1941,9 @@ def test_pct_change(self):
pnl.iat[1, 1] = np.nan
pnl.iat[2, 3] = 60

mask = pnl.isnull()

for axis in range(2):
expected = pnl.ffill(axis=axis) / pnl.ffill(axis=axis).shift(
axis=axis) - 1
expected[mask] = np.nan
result = pnl.pct_change(axis=axis, fill_method='pad')

tm.assert_frame_equal(result, expected)
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/frame/test_timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def test_pct_change_shift_over_nas(self):
df = DataFrame({'a': s, 'b': s})

chg = df.pct_change()
expected = Series([np.nan, 0.5, np.nan, 2.5 / 1.5 - 1, .2])
expected = Series([np.nan, 0.5, 0., 2.5 / 1.5 - 1, .2])
edf = DataFrame({'a': expected, 'b': expected})
assert_frame_equal(chg, edf)

Expand Down
20 changes: 20 additions & 0 deletions pandas/tests/generic/test_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,26 @@ def test_copy_and_deepcopy(self):
assert obj_copy is not obj
self._compare(obj_copy, obj)

@pytest.mark.parametrize("periods,fill_method,limit,exp", [
(1, "ffill", None, [np.nan, np.nan, np.nan, 1, 1, 1.5, 0, 0]),
(1, "ffill", 1, [np.nan, np.nan, np.nan, 1, 1, 1.5, 0, np.nan]),
(1, "bfill", None, [np.nan, 0, 0, 1, 1, 1.5, np.nan, np.nan]),
(1, "bfill", 1, [np.nan, np.nan, 0, 1, 1, 1.5, np.nan, np.nan]),
(-1, "ffill", None, [np.nan, np.nan, -.5, -.5, -.6, 0, 0, np.nan]),
(-1, "ffill", 1, [np.nan, np.nan, -.5, -.5, -.6, 0, np.nan, np.nan]),
(-1, "bfill", None, [0, 0, -.5, -.5, -.6, np.nan, np.nan, np.nan]),
(-1, "bfill", 1, [np.nan, 0, -.5, -.5, -.6, np.nan, np.nan, np.nan])
])
def test_pct_change(self, periods, fill_method, limit, exp):
vals = [np.nan, np.nan, 1, 2, 4, 10, np.nan, np.nan]
obj = self._typ(vals)
func = getattr(obj, 'pct_change')
res = func(periods=periods, fill_method=fill_method, limit=limit)
if type(obj) is DataFrame:
tm.assert_frame_equal(res, DataFrame(exp))
else:
tm.assert_series_equal(res, Series(exp))


class TestNDFrame(object):
# tests that don't fit elsewhere
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/generic/test_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def test_to_xarray(self):
'test_stat_non_defaults_args',
'test_truncate_out_of_bounds',
'test_metadata_propagation', 'test_copy_and_deepcopy',
'test_sample']:
'test_pct_change', 'test_sample']:

def f():
def tester(self):
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/series/test_timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ def test_pct_change_shift_over_nas(self):
s = Series([1., 1.5, np.nan, 2.5, 3.])

chg = s.pct_change()
expected = Series([np.nan, 0.5, np.nan, 2.5 / 1.5 - 1, .2])
expected = Series([np.nan, 0.5, 0., 2.5 / 1.5 - 1, .2])
assert_series_equal(chg, expected)

def test_pct_change_periods_freq(self):
Expand Down

0 comments on commit fb54f40

Please sign in to comment.