Skip to content

Commit e5981d1

Browse files
WillAydharisbal
authored and
harisbal
committed
Fixed pct_change with 'fill_method' returning NaN instead of 0 (pandas-dev#19875)
1 parent 08732e0 commit e5981d1

File tree

7 files changed

+25
-7
lines changed

7 files changed

+25
-7
lines changed

doc/source/whatsnew/v0.23.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,7 @@ Numeric
808808
- Bug in :class:`Index` constructor with ``dtype='uint64'`` where int-like floats were not coerced to :class:`UInt64Index` (:issue:`18400`)
809809
- 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`)
810810
- Multiplication and division of numeric-dtyped :class:`Index` objects with timedelta-like scalars returns ``TimedeltaIndex`` instead of raising ``TypeError`` (:issue:`19333`)
811+
- 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`)
811812

812813

813814
Indexing

pandas/core/generic.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7488,7 +7488,7 @@ def pct_change(self, periods=1, fill_method='pad', limit=None, freq=None,
74887488
**kwargs)) - 1)
74897489
rs = rs.reindex_like(data)
74907490
if freq is None:
7491-
mask = isna(com._values_from_object(self))
7491+
mask = isna(com._values_from_object(data))
74927492
np.putmask(rs.values, mask, np.nan)
74937493
return rs
74947494

pandas/tests/frame/test_analytics.py

-3
Original file line numberDiff line numberDiff line change
@@ -1941,12 +1941,9 @@ def test_pct_change(self):
19411941
pnl.iat[1, 1] = np.nan
19421942
pnl.iat[2, 3] = 60
19431943

1944-
mask = pnl.isnull()
1945-
19461944
for axis in range(2):
19471945
expected = pnl.ffill(axis=axis) / pnl.ffill(axis=axis).shift(
19481946
axis=axis) - 1
1949-
expected[mask] = np.nan
19501947
result = pnl.pct_change(axis=axis, fill_method='pad')
19511948

19521949
tm.assert_frame_equal(result, expected)

pandas/tests/frame/test_timeseries.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def test_pct_change_shift_over_nas(self):
118118
df = DataFrame({'a': s, 'b': s})
119119

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

pandas/tests/generic/test_generic.py

+20
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,26 @@ def test_copy_and_deepcopy(self):
592592
assert obj_copy is not obj
593593
self._compare(obj_copy, obj)
594594

595+
@pytest.mark.parametrize("periods,fill_method,limit,exp", [
596+
(1, "ffill", None, [np.nan, np.nan, np.nan, 1, 1, 1.5, 0, 0]),
597+
(1, "ffill", 1, [np.nan, np.nan, np.nan, 1, 1, 1.5, 0, np.nan]),
598+
(1, "bfill", None, [np.nan, 0, 0, 1, 1, 1.5, np.nan, np.nan]),
599+
(1, "bfill", 1, [np.nan, np.nan, 0, 1, 1, 1.5, np.nan, np.nan]),
600+
(-1, "ffill", None, [np.nan, np.nan, -.5, -.5, -.6, 0, 0, np.nan]),
601+
(-1, "ffill", 1, [np.nan, np.nan, -.5, -.5, -.6, 0, np.nan, np.nan]),
602+
(-1, "bfill", None, [0, 0, -.5, -.5, -.6, np.nan, np.nan, np.nan]),
603+
(-1, "bfill", 1, [np.nan, 0, -.5, -.5, -.6, np.nan, np.nan, np.nan])
604+
])
605+
def test_pct_change(self, periods, fill_method, limit, exp):
606+
vals = [np.nan, np.nan, 1, 2, 4, 10, np.nan, np.nan]
607+
obj = self._typ(vals)
608+
func = getattr(obj, 'pct_change')
609+
res = func(periods=periods, fill_method=fill_method, limit=limit)
610+
if type(obj) is DataFrame:
611+
tm.assert_frame_equal(res, DataFrame(exp))
612+
else:
613+
tm.assert_series_equal(res, Series(exp))
614+
595615

596616
class TestNDFrame(object):
597617
# tests that don't fit elsewhere

pandas/tests/generic/test_panel.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def test_to_xarray(self):
4545
'test_stat_non_defaults_args',
4646
'test_truncate_out_of_bounds',
4747
'test_metadata_propagation', 'test_copy_and_deepcopy',
48-
'test_sample']:
48+
'test_pct_change', 'test_sample']:
4949

5050
def f():
5151
def tester(self):

pandas/tests/series/test_timeseries.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ def test_pct_change_shift_over_nas(self):
352352
s = Series([1., 1.5, np.nan, 2.5, 3.])
353353

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

358358
def test_pct_change_periods_freq(self):

0 commit comments

Comments
 (0)