Skip to content

Commit 72d573e

Browse files
WBarestangirala
authored andcommitted
BUG: Interpolate limit=n GH16282 (pandas-dev#16429)
* BUG: Interpolate limit=n GH16282 * Fix: comment line over the 80 char limit * Test: Added small test for code coverage * DOC: Moved whats new comment from 0.21.0 to 0.20.2 * Update v0.21.0.txt Removed extraneous newline
1 parent 3aa70ae commit 72d573e

File tree

4 files changed

+53
-28
lines changed

4 files changed

+53
-28
lines changed

doc/source/whatsnew/v0.20.2.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ Reshaping
8585

8686
Numeric
8787
^^^^^^^
88-
88+
- Bug in .interpolate(), where limit_direction was not respected when limit=None (default) was passed (:issue:16282)
8989

9090
Categorical
9191
^^^^^^^^^^^

pandas/core/missing.py

+33-27
Original file line numberDiff line numberDiff line change
@@ -160,35 +160,41 @@ def _interp_limit(invalid, fw_limit, bw_limit):
160160
start_nans = set(range(ys.first_valid_index()))
161161
end_nans = set(range(1 + ys.last_valid_index(), len(valid)))
162162

163-
# This is a list of the indexes in the series whose yvalue is currently
164-
# NaN, but whose interpolated yvalue will be overwritten with NaN after
165-
# computing the interpolation. For each index in this list, one of these
166-
# conditions is true of the corresponding NaN in the yvalues:
163+
# violate_limit is a list of the indexes in the series whose yvalue is
164+
# currently NaN, and should still be NaN after the interpolation.
165+
# Specifically:
167166
#
168-
# a) It is one of a chain of NaNs at the beginning of the series, and
169-
# either limit is not specified or limit_direction is 'forward'.
170-
# b) It is one of a chain of NaNs at the end of the series, and limit is
171-
# specified and limit_direction is 'backward' or 'both'.
172-
# c) Limit is nonzero and it is further than limit from the nearest non-NaN
173-
# value (with respect to the limit_direction setting).
167+
# If limit_direction='forward' or None then the list will contain NaNs at
168+
# the beginning of the series, and NaNs that are more than 'limit' away
169+
# from the prior non-NaN.
174170
#
175-
# The default behavior is to fill forward with no limit, ignoring NaNs at
176-
# the beginning (see issues #9218 and #10420)
177-
violate_limit = sorted(start_nans)
178-
179-
if limit is not None:
180-
if not is_integer(limit):
181-
raise ValueError('Limit must be an integer')
182-
if limit < 1:
183-
raise ValueError('Limit must be greater than 0')
184-
if limit_direction == 'forward':
185-
violate_limit = sorted(start_nans | set(_interp_limit(invalid,
186-
limit, 0)))
187-
if limit_direction == 'backward':
188-
violate_limit = sorted(end_nans | set(_interp_limit(invalid, 0,
189-
limit)))
190-
if limit_direction == 'both':
191-
violate_limit = sorted(_interp_limit(invalid, limit, limit))
171+
# If limit_direction='backward' then the list will contain NaNs at
172+
# the end of the series, and NaNs that are more than 'limit' away
173+
# from the subsequent non-NaN.
174+
#
175+
# If limit_direction='both' then the list will contain NaNs that
176+
# are more than 'limit' away from any non-NaN.
177+
#
178+
# If limit=None, then use default behavior of filling an unlimited number
179+
# of NaNs in the direction specified by limit_direction
180+
181+
# default limit is unlimited GH #16282
182+
if limit is None:
183+
limit = len(xvalues)
184+
elif not is_integer(limit):
185+
raise ValueError('Limit must be an integer')
186+
elif limit < 1:
187+
raise ValueError('Limit must be greater than 0')
188+
189+
# each possible limit_direction
190+
if limit_direction == 'forward':
191+
violate_limit = sorted(start_nans |
192+
set(_interp_limit(invalid, limit, 0)))
193+
elif limit_direction == 'backward':
194+
violate_limit = sorted(end_nans |
195+
set(_interp_limit(invalid, 0, limit)))
196+
elif limit_direction == 'both':
197+
violate_limit = sorted(_interp_limit(invalid, limit, limit))
192198

193199
xvalues = getattr(xvalues, 'values', xvalues)
194200
yvalues = getattr(yvalues, 'values', yvalues)

pandas/tests/series/test_missing.py

+18
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,24 @@ def test_interp_limit_forward(self):
931931
limit_direction='FORWARD')
932932
assert_series_equal(result, expected)
933933

934+
def test_interp_unlimited(self):
935+
# these test are for issue #16282 default Limit=None is unlimited
936+
s = Series([np.nan, 1., 3., np.nan, np.nan, np.nan, 11., np.nan])
937+
expected = Series([1., 1., 3., 5., 7., 9., 11., 11.])
938+
result = s.interpolate(method='linear',
939+
limit_direction='both')
940+
assert_series_equal(result, expected)
941+
942+
expected = Series([np.nan, 1., 3., 5., 7., 9., 11., 11.])
943+
result = s.interpolate(method='linear',
944+
limit_direction='forward')
945+
assert_series_equal(result, expected)
946+
947+
expected = Series([1., 1., 3., 5., 7., 9., 11., np.nan])
948+
result = s.interpolate(method='linear',
949+
limit_direction='backward')
950+
assert_series_equal(result, expected)
951+
934952
def test_interp_limit_bad_direction(self):
935953
s = Series([1, 3, np.nan, np.nan, np.nan, 11])
936954

pandas/tests/test_common.py

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def test_mut_exclusive():
1818
com._mut_exclusive(a=1, b=2)
1919
assert com._mut_exclusive(a=1, b=None) == 1
2020
assert com._mut_exclusive(major=None, major_axis=None) is None
21+
assert com._mut_exclusive(a=None, b=2) == 2
2122

2223

2324
def test_get_callable_name():

0 commit comments

Comments
 (0)