Skip to content

Bug: Raise ValueError with interpolate & fillna limit = 0 (#9217) #14994

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

mroeschke
Copy link
Member

@mroeschke mroeschke commented Dec 26, 2016

Add similar logic to fillna

@@ -3704,6 +3704,8 @@ def interpolate(self, method='linear', axis=0, limit=None, inplace=False,
"""
Interpolate values according to different methods.
"""
if isinstance(limit, int) and not limit > 0:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually might need this check on fillna as well (if it's not there)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use is_integer instead of this check

@mroeschke mroeschke changed the title Bug: Raise ValueError with interpolate limit = 0 (#9217) Bug: Raise ValueError with interpolate & fillna limit = 0 (#9217) Dec 26, 2016
@mroeschke
Copy link
Member Author

Good idea! Added check to fillna as well. Will ping again on green.

@codecov-io
Copy link

codecov-io commented Dec 27, 2016

Codecov Report

Merging #14994 into master will increase coverage by <.01%.
The diff coverage is 100%.

@@            Coverage Diff             @@
##           master   #14994      +/-   ##
==========================================
+ Coverage   90.42%   90.42%   +<.01%     
==========================================
  Files         134      134              
  Lines       49357    49365       +8     
==========================================
+ Hits        44632    44640       +8     
  Misses       4725     4725
Impacted Files Coverage Δ
pandas/core/generic.py 96.33% <ø> (ø)
pandas/core/missing.py 84.95% <100%> (+0.19%)
pandas/core/internals.py 94.15% <100%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update dda3c42...c1790ee. Read the comment docs.

@mroeschke
Copy link
Member Author

Ping all green

@sinhrks sinhrks added Error Reporting Incorrect or improved errors from pandas Missing-data np.nan, pd.NaT, pd.NA, dropna, isnull, interpolate labels Dec 27, 2016
@sinhrks sinhrks added this to the 0.20.0 milestone Dec 27, 2016
@jreback
Copy link
Contributor

jreback commented Dec 27, 2016

ok these need to be change here instead: https://github.com/pandas-dev/pandas/blob/master/pandas/src/algos_common_helper.pxi.in#L85 (there are 4 places where this is hit). This is more appropriate as we are already checking the limit and its closer to the actual code path.

I think you need some more tests for < 0 (which currently should raise), and == 0 (which I think you added)

@mroeschke
Copy link
Member Author

Sorry for the delay in response.

I am not too familiar with the cython portion of the code base. Interestingly in master (0d3ecfa), if negative limits are used in fillna or interpolate, an error is not thrown. Is the cython code supposed to throw an error here?

In [2]: s = pd.Series([1,2,3,None])

In [3]: s.interpolate(limit=-1)
Out[3]: 
0    1.0
1    2.0
2    3.0
3    NaN
dtype: float64

In [4]: s.fillna(4, limit=-1)
Out[4]: 
0    1.0
1    2.0
2    3.0
3    NaN
dtype: float64

Added tests on my branch to test the negative limits.

@jreback
Copy link
Contributor

jreback commented Dec 30, 2016

it should but might be trapped somewhere

@mroeschke
Copy link
Member Author

Ah, possibly lost in a try/except?

@jreback
Copy link
Contributor

jreback commented Dec 30, 2016

@mroeschke somewhere, you will have to trace it.

@mroeschke
Copy link
Member Author

So I traced .fillna(4, limit=-1):

--- modulename: series, funcname: fillna
series.py(2366):         return super(Series, self).fillna(value=value, method=method,
series.py(2367):                                           axis=axis, inplace=inplace,
series.py(2368):                                           limit=limit, downcast=downcast,
series.py(2369):                                           **kwargs)
--- modulename: generic, funcname: fillna
generic.py(3260):         if isinstance(value, (list, tuple)):
generic.py(3263):         self._consolidate_inplace()
--- modulename: generic, funcname: _consolidate_inplace
generic.py(2855):         def f():
generic.py(2858):         self._protect_consolidate(f)
--- modulename: generic, funcname: _protect_consolidate
generic.py(2846):         blocks_before = len(self._data.blocks)
generic.py(2847):         result = f()
--- modulename: generic, funcname: f
generic.py(2856):             self._data = self._data.consolidate()
--- modulename: internals, funcname: consolidate
internals.py(3522):         if self.is_consolidated():
--- modulename: internals, funcname: is_consolidated
internals.py(4199):         return True
internals.py(3523):             return self
--- modulename: generic, funcname: __setattr__
generic.py(2812):         try:
generic.py(2813):             object.__getattribute__(self, name)
generic.py(2814):             return object.__setattr__(self, name, value)
generic.py(2848):         if len(self._data.blocks) != blocks_before:
generic.py(2850):         return result
generic.py(3267):         if axis is None:
generic.py(3268):             axis = 0
generic.py(3269):         axis = self._get_axis_number(axis)
--- modulename: generic, funcname: _get_axis_number
generic.py(328):         axis = self._AXIS_ALIASES.get(axis, axis)
generic.py(329):         if is_integer(axis):
generic.py(330):             if axis in self._AXIS_NAMES:
generic.py(331):                 return axis
generic.py(3270):         method = missing.clean_fill_method(method)
--- modulename: missing, funcname: clean_fill_method
missing.py(68):     if method in [None, 'asfreq']:
missing.py(69):         return None
generic.py(3272):         from pandas import DataFrame
generic.py(3273):         if value is None:
generic.py(3309):             if method is not None:
generic.py(3312):             if len(self._get_axis(axis)) == 0:
--- modulename: generic, funcname: _get_axis
generic.py(354):         name = self._get_axis_name(axis)
--- modulename: generic, funcname: _get_axis_name
generic.py(341):         axis = self._AXIS_ALIASES.get(axis, axis)
generic.py(342):         if isinstance(axis, string_types):
generic.py(346):             try:
generic.py(347):                 return self._AXIS_NAMES[axis]
generic.py(355):         return getattr(self, name)
--- modulename: range, funcname: __len__
range.py(462):         return max(0, -(-(self._stop - self._start) // self._step))
generic.py(3315):             if self.ndim == 1:
--- modulename: base, funcname: ndim
base.py(824):         return 1
generic.py(3316):                 if isinstance(value, (dict, ABCSeries)):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
generic.py(3319):                 elif not is_list_like(value):
--- modulename: inference, funcname: is_list_like
inference.py(56):     return (hasattr(arg, '__iter__') and
generic.py(3320):                     pass
generic.py(3325):                 new_data = self._data.fillna(value=value, limit=limit,
generic.py(3326):                                              inplace=inplace,
generic.py(3327):                                              downcast=downcast)
--- modulename: internals, funcname: fillna
internals.py(3184):         return self.apply('fillna', **kwargs)
--- modulename: internals, funcname: apply
internals.py(3001):         result_blocks = []
internals.py(3004):         if filter is not None:
internals.py(3012):         if consolidate:
internals.py(3013):             self._consolidate_inplace()
--- modulename: internals, funcname: _consolidate_inplace
internals.py(4205):         pass
internals.py(3015):         if f == 'where':
internals.py(3021):         elif f == 'putmask':
internals.py(3027):         elif f == 'eval':
internals.py(3030):         elif f == 'fillna':
internals.py(3033):             align_copy = False
internals.py(3034):             align_keys = ['value']
internals.py(3038):         aligned_args = dict((k, kwargs[k])
internals.py(3039):                             for k in align_keys
--- modulename: internals, funcname: <genexpr>
internals.py(3038):         aligned_args = dict((k, kwargs[k])
internals.py(3039):                             for k in align_keys
internals.py(3040):                             if hasattr(kwargs[k], 'reindex_axis'))
internals.py(3038):         aligned_args = dict((k, kwargs[k])
internals.py(3042):         for b in self.blocks:
internals.py(3043):             if filter is not None:
internals.py(3048):             if aligned_args:
internals.py(3056):             kwargs['mgr'] = self
internals.py(3057):             applied = getattr(b, f)(**kwargs)
--- modulename: internals, funcname: fillna
internals.py(364):         if not self._can_hold_na:
internals.py(370):         original_value = value
internals.py(371):         mask = isnull(self.values)
--- modulename: missing, funcname: isnull
missing.py(44):     return _isnull(obj)
--- modulename: missing, funcname: _isnull_new
missing.py(48):     if is_scalar(obj):
missing.py(51):     elif isinstance(obj, ABCMultiIndex):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(53):     elif isinstance(obj, (ABCSeries, np.ndarray, ABCIndexClass)):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(54):         return _isnull_ndarraylike(obj)
--- modulename: missing, funcname: _isnull_ndarraylike
missing.py(121):     values = getattr(obj, 'values', obj)
missing.py(122):     dtype = values.dtype
missing.py(124):     if is_string_dtype(dtype):
--- modulename: common, funcname: is_string_dtype
common.py(105):     dtype = _get_dtype(arr_or_dtype)
--- modulename: common, funcname: _get_dtype
common.py(345):     if isinstance(arr_or_dtype, np.dtype):
common.py(346):         return arr_or_dtype
common.py(106):     return dtype.kind in ('O', 'S', 'U') and not is_period_dtype(dtype)
missing.py(142):     elif needs_i8_conversion(obj):
--- modulename: common, funcname: needs_i8_conversion
common.py(276):     return (is_datetime_or_timedelta_dtype(arr_or_dtype) or
--- modulename: common, funcname: is_datetime_or_timedelta_dtype
common.py(200):     tipo = _get_dtype_type(arr_or_dtype)
--- modulename: common, funcname: _get_dtype_type
common.py(369):     if isinstance(arr_or_dtype, np.dtype):
common.py(371):     elif isinstance(arr_or_dtype, type):
common.py(373):     elif isinstance(arr_or_dtype, CategoricalDtype):
common.py(375):     elif isinstance(arr_or_dtype, DatetimeTZDtype):
common.py(377):     elif isinstance(arr_or_dtype, PeriodDtype):
common.py(379):     elif isinstance(arr_or_dtype, string_types):
common.py(387):     try:
common.py(388):         return arr_or_dtype.dtype.type
common.py(201):     return issubclass(tipo, (np.datetime64, np.timedelta64))
common.py(277):             is_datetime64tz_dtype(arr_or_dtype) or
--- modulename: common, funcname: is_datetime64tz_dtype
common.py(88):     return DatetimeTZDtype.is_dtype(arr_or_dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(79):         if hasattr(dtype, 'dtype'):
dtypes.py(80):             dtype = dtype.dtype
dtypes.py(81):         if isinstance(dtype, cls):
dtypes.py(83):         elif isinstance(dtype, np.dtype):
dtypes.py(84):             return False
common.py(278):             is_period_dtype(arr_or_dtype))
--- modulename: common, funcname: is_period_dtype
common.py(97):     return PeriodDtype.is_dtype(arr_or_dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(354):         if isinstance(dtype, compat.string_types):
dtypes.py(367):         return super(PeriodDtype, cls).is_dtype(dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(79):         if hasattr(dtype, 'dtype'):
dtypes.py(80):             dtype = dtype.dtype
dtypes.py(81):         if isinstance(dtype, cls):
dtypes.py(83):         elif isinstance(dtype, np.dtype):
dtypes.py(84):             return False
missing.py(146):         result = np.isnan(values)
missing.py(149):     if isinstance(obj, ABCSeries):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(153):     return result
internals.py(372):         if limit is not None:
internals.py(373):             if self.ndim > 2:
internals.py(376):             mask[mask.cumsum(self.ndim - 1) > limit] = False
internals.py(379):         try:
internals.py(380):             values, _, value, _ = self._try_coerce_args(self.values, value)
--- modulename: internals, funcname: _try_coerce_args
internals.py(576):         return values, False, other, False
internals.py(381):             blocks = self.putmask(mask, value, inplace=inplace)
--- modulename: internals, funcname: putmask
internals.py(802):         new_values = self.values if inplace else self.values.copy()
internals.py(804):         if hasattr(new, 'reindex_axis'):
internals.py(807):         if hasattr(mask, 'reindex_axis'):
internals.py(811):         if not is_list_like(new) and isnull(new) and not self.is_object:
--- modulename: inference, funcname: is_list_like
inference.py(56):     return (hasattr(arg, '__iter__') and
--- modulename: missing, funcname: isnull
missing.py(44):     return _isnull(obj)
--- modulename: missing, funcname: _isnull_new
missing.py(48):     if is_scalar(obj):
missing.py(49):         return lib.checknull(obj)
internals.py(814):         if self._can_hold_element(new):
--- modulename: internals, funcname: _can_hold_element
internals.py(1555):         if is_list_like(element):
--- modulename: inference, funcname: is_list_like
inference.py(56):     return (hasattr(arg, '__iter__') and
internals.py(1560):         return (isinstance(element, (float, int, np.float_, np.int_)) and
internals.py(1561):                 not isinstance(element, (bool, np.bool_, datetime, timedelta,
internals.py(1562):                                          np.datetime64, np.timedelta64)))
internals.py(815):             if transpose:
internals.py(818):             new = self._try_cast(new)
--- modulename: internals, funcname: _try_cast
internals.py(1565):         try:
internals.py(1566):             return float(element)
internals.py(822):             if getattr(new, 'ndim', 0) >= 1:
internals.py(828):             np.putmask(new_values, mask, new)
internals.py(882):         if inplace:
internals.py(885):         if transpose:
internals.py(888):         return [self.make_block(new_values, fastpath=True)]
--- modulename: internals, funcname: make_block
internals.py(195):         if placement is None:
internals.py(196):             placement = self.mgr_locs
--- modulename: internals, funcname: mgr_locs
internals.py(181):         return self._mgr_locs
internals.py(197):         if ndim is None:
internals.py(198):             ndim = self.ndim
internals.py(200):         return make_block(values, placement=placement, ndim=ndim, **kwargs)
--- modulename: internals, funcname: make_block
internals.py(2652):     if klass is None:
internals.py(2653):         dtype = dtype or values.dtype
internals.py(2654):         vtype = dtype.type
internals.py(2656):         if isinstance(values, SparseArray):
internals.py(2658):         elif issubclass(vtype, np.floating):
internals.py(2659):             klass = FloatBlock
internals.py(2686):     return klass(values, ndim=ndim, fastpath=fastpath, placement=placement)
--- modulename: internals, funcname: __init__
internals.py(97):         if ndim is None:
internals.py(99):         elif values.ndim != ndim:
internals.py(101):         self.ndim = ndim
internals.py(103):         self.mgr_locs = placement
--- modulename: internals, funcname: mgr_locs
internals.py(218):         if not isinstance(new_mgr_locs, BlockPlacement):
internals.py(221):         self._mgr_locs = new_mgr_locs
internals.py(104):         self.values = values
internals.py(106):         if ndim and len(self.mgr_locs) != len(self.values):
--- modulename: internals, funcname: mgr_locs
internals.py(181):         return self._mgr_locs
internals.py(382):             blocks = [b.make_block(values=self._try_coerce_result(b.values))
internals.py(383):                       for b in blocks]
--- modulename: internals, funcname: _try_coerce_result
internals.py(580):         return result
--- modulename: internals, funcname: make_block
internals.py(195):         if placement is None:
internals.py(196):             placement = self.mgr_locs
--- modulename: internals, funcname: mgr_locs
internals.py(181):         return self._mgr_locs
internals.py(197):         if ndim is None:
internals.py(198):             ndim = self.ndim
internals.py(200):         return make_block(values, placement=placement, ndim=ndim, **kwargs)
--- modulename: internals, funcname: make_block
internals.py(2652):     if klass is None:
internals.py(2653):         dtype = dtype or values.dtype
internals.py(2654):         vtype = dtype.type
internals.py(2656):         if isinstance(values, SparseArray):
internals.py(2658):         elif issubclass(vtype, np.floating):
internals.py(2659):             klass = FloatBlock
internals.py(2686):     return klass(values, ndim=ndim, fastpath=fastpath, placement=placement)
--- modulename: internals, funcname: __init__
internals.py(97):         if ndim is None:
internals.py(99):         elif values.ndim != ndim:
internals.py(101):         self.ndim = ndim
internals.py(103):         self.mgr_locs = placement
--- modulename: internals, funcname: mgr_locs
internals.py(218):         if not isinstance(new_mgr_locs, BlockPlacement):
internals.py(221):         self._mgr_locs = new_mgr_locs
internals.py(104):         self.values = values
internals.py(106):         if ndim and len(self.mgr_locs) != len(self.values):
--- modulename: internals, funcname: mgr_locs
internals.py(181):         return self._mgr_locs
internals.py(383):                       for b in blocks]
internals.py(384):             return self._maybe_downcast(blocks, downcast)
--- modulename: internals, funcname: _maybe_downcast
internals.py(402):         if downcast is None and self.is_float:
internals.py(403):             return blocks
internals.py(3058):             result_blocks = _extend_blocks(applied, result_blocks)
--- modulename: internals, funcname: _extend_blocks
internals.py(4553):     if blocks is None:
internals.py(4555):     if isinstance(result, list):
internals.py(4556):         for r in result:
internals.py(4557):             if isinstance(r, list):
internals.py(4560):                 blocks.append(r)
internals.py(4556):         for r in result:
internals.py(4565):     return blocks
internals.py(3042):         for b in self.blocks:
internals.py(3060):         if len(result_blocks) == 0:
internals.py(3062):         bm = self.__class__(result_blocks, axes or self.axes,
internals.py(3063):                             do_integrity_check=do_integrity_check)
--- modulename: internals, funcname: __init__
internals.py(4034):         if isinstance(axis, list):
internals.py(4035):             if len(axis) != 1:
internals.py(4038):             axis = axis[0]
internals.py(4041):         if fastpath:
internals.py(4053):             self.axes = [_ensure_index(axis)]
--- modulename: base, funcname: _ensure_index
base.py(3661):     if isinstance(index_like, Index):
base.py(3662):         if copy:
base.py(3664):         return index_like
internals.py(4056):             if isinstance(block, list):
internals.py(4059):                 if len(block) > 1:
internals.py(4064):                 if len(block) != 1:
internals.py(4067):                 block = block[0]
internals.py(4069):         if not isinstance(block, Block):
internals.py(4073):         self.blocks = [block]
internals.py(3064):         bm._consolidate_inplace()
--- modulename: internals, funcname: _consolidate_inplace
internals.py(4205):         pass
internals.py(3065):         return bm
generic.py(3351):         if inplace:
generic.py(3354):             return self._constructor(new_data).__finalize__(self)
--- modulename: series, funcname: _constructor
series.py(266):         return Series
--- modulename: series, funcname: __init__
series.py(140):         if fastpath:
series.py(152):             if index is not None:
series.py(155):             if data is None:
series.py(157):             if dtype is not None:
series.py(160):             if isinstance(data, MultiIndex):
series.py(163):             elif isinstance(data, Index):
series.py(170):             elif isinstance(data, np.ndarray):
series.py(172):             elif isinstance(data, Series):
series.py(180):             elif isinstance(data, dict):
series.py(207):             elif isinstance(data, SingleBlockManager):
series.py(208):                 if index is None:
series.py(209):                     index = data.index
--- modulename: internals, funcname: index
internals.py(4141):         return self.axes[0]
series.py(231):             if index is None:
series.py(237):             if isinstance(data, SingleBlockManager):
series.py(238):                 if dtype is not None:
series.py(240):                 elif copy:
series.py(248):         generic.NDFrame.__init__(self, data, fastpath=True)
--- modulename: generic, funcname: __init__
generic.py(117):         if not fastpath:
generic.py(127):         object.__setattr__(self, 'is_copy', None)
generic.py(128):         object.__setattr__(self, '_data', data)
generic.py(129):         object.__setattr__(self, '_item_cache', {})
series.py(250):         self.name = name
--- modulename: generic, funcname: __setattr__
generic.py(2812):         try:
generic.py(2813):             object.__getattribute__(self, name)
--- modulename: series, funcname: name
series.py(325):         return self._name
--- modulename: generic, funcname: __getattr__
generic.py(2795):         if (name in self._internal_names_set or name in self._metadata or
generic.py(2797):             return object.__getattribute__(self, name)
generic.py(2815):         except AttributeError:
generic.py(2816):             pass
generic.py(2820):         if name in self._internal_names_set:
generic.py(2822):         elif name in self._metadata:
generic.py(2823):             object.__setattr__(self, name, value)
--- modulename: series, funcname: name
series.py(329):         if value is not None and not is_hashable(value):
series.py(331):         object.__setattr__(self, '_name', value)
series.py(251):         self._set_axis(0, index, fastpath=True)
--- modulename: series, funcname: _set_axis
series.py(290):         if not fastpath:
series.py(293):         is_all_dates = labels.is_all_dates
--- modulename: numeric, funcname: is_all_dates
numeric.py(136):         return False
series.py(294):         if is_all_dates:
series.py(307):         self._set_subtyp(is_all_dates)
--- modulename: series, funcname: _set_subtyp
series.py(314):         if is_all_dates:
series.py(317):             object.__setattr__(self, '_subtyp', 'series')
series.py(309):         object.__setattr__(self, '_index', labels)
series.py(310):         if not fastpath:
--- modulename: generic, funcname: __finalize__
generic.py(2782):         if isinstance(other, NDFrame):
generic.py(2783):             for name in self._metadata:
generic.py(2784):                 object.__setattr__(self, name, getattr(other, name, None))
--- modulename: series, funcname: name
series.py(325):         return self._name
--- modulename: series, funcname: name
series.py(329):         if value is not None and not is_hashable(value):
series.py(331):         object.__setattr__(self, '_name', value)
generic.py(2783):             for name in self._metadata:
generic.py(2785):         return self
--- modulename: trace, funcname: _unsettrace
trace.py(80):         sys.settrace(None)

And .interpolate(limit=-1):

--- modulename: generic, funcname: interpolate
generic.py(3708):         if self.ndim > 2:
--- modulename: base, funcname: ndim
base.py(824):         return 1
generic.py(3712):         if axis == 0:
generic.py(3713):             ax = self._info_axis_name
generic.py(3714):             _maybe_transposed_self = self
generic.py(3720):         ax = _maybe_transposed_self._get_axis_number(ax)
--- modulename: generic, funcname: _get_axis_number
generic.py(328):         axis = self._AXIS_ALIASES.get(axis, axis)
generic.py(329):         if is_integer(axis):
generic.py(333):             try:
generic.py(334):                 return self._AXIS_NUMBERS[axis]
generic.py(3722):         if _maybe_transposed_self.ndim == 2:
--- modulename: base, funcname: ndim
base.py(824):         return 1
generic.py(3725):             alt_ax = ax
generic.py(3727):         if (isinstance(_maybe_transposed_self.index, MultiIndex) and
generic.py(3732):         if _maybe_transposed_self._data.get_dtype_counts().get(
--- modulename: internals, funcname: get_dtype_counts
internals.py(4161):         return {self.dtype.name: 1}
--- modulename: internals, funcname: dtype
internals.py(4150):         return self._block.dtype
--- modulename: internals, funcname: _block
internals.py(4080):         return self.blocks[0]
--- modulename: internals, funcname: dtype
internals.py(299):         return self.values.dtype
generic.py(3733):                 'object') == len(_maybe_transposed_self.T):
--- modulename: base, funcname: transpose
base.py(808):         nv.validate_transpose(args, kwargs)
--- modulename: function, funcname: __call__
function.py(39):         fname = self.fname if fname is None else fname
function.py(41):                                max_fname_arg_count is None
function.py(43):         method = self.method if method is None else method
function.py(45):         if method == 'args':
function.py(47):         elif method == 'kwargs':
function.py(49):         elif method == 'both':
function.py(50):             validate_args_and_kwargs(fname, args, kwargs,
function.py(51):                                      max_fname_arg_count,
function.py(52):                                      self.defaults)
--- modulename: validators, funcname: validate_args_and_kwargs
validators.py(204):     _check_arg_length(fname, args + tuple(kwargs.values()),
validators.py(205):                       max_fname_arg_count, compat_args)
--- modulename: validators, funcname: _check_arg_length
validators.py(16):     if max_fname_arg_count < 0:
validators.py(19):     if len(args) > len(compat_args):
validators.py(209):     args_dict = dict(zip(compat_args, args))
validators.py(211):     for key in args_dict:
validators.py(216):     kwargs.update(args_dict)
validators.py(217):     validate_kwargs(fname, kwargs, compat_args)
--- modulename: validators, funcname: validate_kwargs
validators.py(154):     kwds = kwargs.copy()
validators.py(155):     _check_for_invalid_keys(fname, kwargs, compat_args)
--- modulename: validators, funcname: _check_for_invalid_keys
validators.py(120):     diff = set(kwargs) - set(compat_args)
validators.py(122):     if diff:
validators.py(156):     _check_for_default_values(fname, kwds, compat_args)
--- modulename: validators, funcname: _check_for_default_values
validators.py(40):     for key in arg_val_dict:
base.py(809):         return self
--- modulename: series, funcname: __len__
series.py(468):         return len(self._data)
--- modulename: internals, funcname: __len__
internals.py(2953):         return len(self.items)
--- modulename: internals, funcname: _get_items
internals.py(2864):         return self.axes[0]
--- modulename: range, funcname: __len__
range.py(462):         return max(0, -(-(self._stop - self._start) // self._step))
generic.py(3737):         if method == 'linear':
generic.py(3739):             index = np.arange(len(_maybe_transposed_self._get_axis(alt_ax)))
--- modulename: generic, funcname: _get_axis
generic.py(354):         name = self._get_axis_name(axis)
--- modulename: generic, funcname: _get_axis_name
generic.py(341):         axis = self._AXIS_ALIASES.get(axis, axis)
generic.py(342):         if isinstance(axis, string_types):
generic.py(346):             try:
generic.py(347):                 return self._AXIS_NAMES[axis]
generic.py(355):         return getattr(self, name)
--- modulename: range, funcname: __len__
range.py(462):         return max(0, -(-(self._stop - self._start) // self._step))
generic.py(3743):         if pd.isnull(index).any():
--- modulename: missing, funcname: isnull
missing.py(44):     return _isnull(obj)
--- modulename: missing, funcname: _isnull_new
missing.py(48):     if is_scalar(obj):
missing.py(51):     elif isinstance(obj, ABCMultiIndex):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(53):     elif isinstance(obj, (ABCSeries, np.ndarray, ABCIndexClass)):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(54):         return _isnull_ndarraylike(obj)
--- modulename: missing, funcname: _isnull_ndarraylike
missing.py(121):     values = getattr(obj, 'values', obj)
missing.py(122):     dtype = values.dtype
missing.py(124):     if is_string_dtype(dtype):
--- modulename: common, funcname: is_string_dtype
common.py(105):     dtype = _get_dtype(arr_or_dtype)
--- modulename: common, funcname: _get_dtype
common.py(345):     if isinstance(arr_or_dtype, np.dtype):
common.py(346):         return arr_or_dtype
common.py(106):     return dtype.kind in ('O', 'S', 'U') and not is_period_dtype(dtype)
missing.py(142):     elif needs_i8_conversion(obj):
--- modulename: common, funcname: needs_i8_conversion
common.py(276):     return (is_datetime_or_timedelta_dtype(arr_or_dtype) or
--- modulename: common, funcname: is_datetime_or_timedelta_dtype
common.py(200):     tipo = _get_dtype_type(arr_or_dtype)
--- modulename: common, funcname: _get_dtype_type
common.py(369):     if isinstance(arr_or_dtype, np.dtype):
common.py(371):     elif isinstance(arr_or_dtype, type):
common.py(373):     elif isinstance(arr_or_dtype, CategoricalDtype):
common.py(375):     elif isinstance(arr_or_dtype, DatetimeTZDtype):
common.py(377):     elif isinstance(arr_or_dtype, PeriodDtype):
common.py(379):     elif isinstance(arr_or_dtype, string_types):
common.py(387):     try:
common.py(388):         return arr_or_dtype.dtype.type
common.py(201):     return issubclass(tipo, (np.datetime64, np.timedelta64))
common.py(277):             is_datetime64tz_dtype(arr_or_dtype) or
--- modulename: common, funcname: is_datetime64tz_dtype
common.py(88):     return DatetimeTZDtype.is_dtype(arr_or_dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(79):         if hasattr(dtype, 'dtype'):
dtypes.py(80):             dtype = dtype.dtype
dtypes.py(81):         if isinstance(dtype, cls):
dtypes.py(83):         elif isinstance(dtype, np.dtype):
dtypes.py(84):             return False
common.py(278):             is_period_dtype(arr_or_dtype))
--- modulename: common, funcname: is_period_dtype
common.py(97):     return PeriodDtype.is_dtype(arr_or_dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(354):         if isinstance(dtype, compat.string_types):
dtypes.py(367):         return super(PeriodDtype, cls).is_dtype(dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(79):         if hasattr(dtype, 'dtype'):
dtypes.py(80):             dtype = dtype.dtype
dtypes.py(81):         if isinstance(dtype, cls):
dtypes.py(83):         elif isinstance(dtype, np.dtype):
dtypes.py(84):             return False
missing.py(146):         result = np.isnan(values)
missing.py(149):     if isinstance(obj, ABCSeries):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(153):     return result
--- modulename: _methods, funcname: _any
_methods.py(38):     return umr_any(a, axis, dtype, out, keepdims)
generic.py(3747):         data = _maybe_transposed_self._data
generic.py(3748):         new_data = data.interpolate(method=method, axis=ax, index=index,
generic.py(3749):                                     values=_maybe_transposed_self, limit=limit,
generic.py(3750):                                     limit_direction=limit_direction,
generic.py(3751):                                     inplace=inplace, downcast=downcast,
generic.py(3752):                                     **kwargs)
--- modulename: internals, funcname: interpolate
internals.py(3178):         return self.apply('interpolate', **kwargs)
--- modulename: internals, funcname: apply
internals.py(3001):         result_blocks = []
internals.py(3004):         if filter is not None:
internals.py(3012):         if consolidate:
internals.py(3013):             self._consolidate_inplace()
--- modulename: internals, funcname: _consolidate_inplace
internals.py(4205):         pass
internals.py(3015):         if f == 'where':
internals.py(3021):         elif f == 'putmask':
internals.py(3027):         elif f == 'eval':
internals.py(3030):         elif f == 'fillna':
internals.py(3036):             align_keys = []
internals.py(3038):         aligned_args = dict((k, kwargs[k])
internals.py(3039):                             for k in align_keys
--- modulename: internals, funcname: <genexpr>
internals.py(3038):         aligned_args = dict((k, kwargs[k])
internals.py(3042):         for b in self.blocks:
internals.py(3043):             if filter is not None:
internals.py(3048):             if aligned_args:
internals.py(3056):             kwargs['mgr'] = self
internals.py(3057):             applied = getattr(b, f)(**kwargs)
--- modulename: internals, funcname: interpolate
internals.py(894):         def check_int_bool(self, inplace):
internals.py(904):         try:
internals.py(905):             m = missing.clean_fill_method(method)
--- modulename: missing, funcname: clean_fill_method
missing.py(68):     if method in [None, 'asfreq']:
missing.py(71):     if isinstance(method, string_types):
missing.py(72):         method = method.lower()
missing.py(73):         if method == 'ffill':
missing.py(75):         elif method == 'bfill':
missing.py(78):     valid_methods = ['pad', 'backfill']
missing.py(79):     expecting = 'pad (ffill) or backfill (bfill)'
missing.py(80):     if allow_nearest:
missing.py(83):     if method not in valid_methods:
missing.py(84):         msg = ('Invalid fill method. Expecting %s. Got %s' %
missing.py(85):                (expecting, method))
missing.py(86):         raise ValueError(msg)
internals.py(906):         except:
internals.py(907):             m = None
internals.py(909):         if m is not None:
internals.py(919):         try:
internals.py(920):             m = missing.clean_interp_method(method, **kwargs)
--- modulename: missing, funcname: clean_interp_method
missing.py(91):     order = kwargs.get('order')
missing.py(92):     valid = ['linear', 'time', 'index', 'values', 'nearest', 'zero', 'slinear',
missing.py(93):              'quadratic', 'cubic', 'barycentric', 'polynomial', 'krogh',
missing.py(94):              'piecewise_polynomial', 'pchip', 'akima', 'spline',
missing.py(95):              'from_derivatives']
missing.py(96):     if method in ('spline', 'polynomial') and order is None:
missing.py(99):     if method not in valid:
missing.py(103):     return method
internals.py(924):         if m is not None:
internals.py(925):             r = check_int_bool(self, inplace)
--- modulename: internals, funcname: check_int_bool
internals.py(897):             if (self.is_bool or self.is_integer) and not self.is_timedelta:
internals.py(926):             if r is not None:
internals.py(928):             return self._interpolate(method=m, index=index, values=values,
internals.py(929):                                      axis=axis, limit=limit,
internals.py(930):                                      limit_direction=limit_direction,
internals.py(931):                                      fill_value=fill_value, inplace=inplace,
internals.py(932):                                      downcast=downcast, mgr=mgr, **kwargs)
--- modulename: internals, funcname: _interpolate
internals.py(967):         data = self.values if inplace else self.values.copy()
internals.py(970):         if not self.is_float:
internals.py(975):         if fill_value is None:
internals.py(976):             fill_value = self.fill_value
--- modulename: internals, funcname: fill_value
internals.py(177):         return np.nan
internals.py(978):         if method in ('krogh', 'piecewise_polynomial', 'pchip'):
internals.py(984):         def func(x):
internals.py(995):         interp_values = np.apply_along_axis(func, axis, data)
--- modulename: shape_base, funcname: apply_along_axis
shape_base.py(77):     arr = asarray(arr)
--- modulename: numeric, funcname: asarray
numeric.py(482):     return array(a, dtype, copy=False, order=order)
shape_base.py(78):     nd = arr.ndim
shape_base.py(79):     if axis < 0:
shape_base.py(81):     if (axis >= nd):
shape_base.py(84):     ind = [0]*(nd-1)
shape_base.py(85):     i = zeros(nd, 'O')
shape_base.py(86):     indlist = list(range(nd))
shape_base.py(87):     indlist.remove(axis)
shape_base.py(88):     i[axis] = slice(None, None)
shape_base.py(89):     outshape = asarray(arr.shape).take(indlist)
--- modulename: numeric, funcname: asarray
numeric.py(482):     return array(a, dtype, copy=False, order=order)
shape_base.py(90):     i.put(indlist, ind)
shape_base.py(91):     res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
--- modulename: internals, funcname: func
internals.py(989):             return missing.interpolate_1d(index, x, method=method, limit=limit,
internals.py(990):                                           limit_direction=limit_direction,
internals.py(991):                                           fill_value=fill_value,
internals.py(992):                                           bounds_error=False, **kwargs)
--- modulename: missing, funcname: interpolate_1d
missing.py(118):     invalid = isnull(yvalues)
--- modulename: missing, funcname: isnull
missing.py(44):     return _isnull(obj)
--- modulename: missing, funcname: _isnull_new
missing.py(48):     if is_scalar(obj):
missing.py(51):     elif isinstance(obj, ABCMultiIndex):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(53):     elif isinstance(obj, (ABCSeries, np.ndarray, ABCIndexClass)):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(54):         return _isnull_ndarraylike(obj)
--- modulename: missing, funcname: _isnull_ndarraylike
missing.py(121):     values = getattr(obj, 'values', obj)
missing.py(122):     dtype = values.dtype
missing.py(124):     if is_string_dtype(dtype):
--- modulename: common, funcname: is_string_dtype
common.py(105):     dtype = _get_dtype(arr_or_dtype)
--- modulename: common, funcname: _get_dtype
common.py(345):     if isinstance(arr_or_dtype, np.dtype):
common.py(346):         return arr_or_dtype
common.py(106):     return dtype.kind in ('O', 'S', 'U') and not is_period_dtype(dtype)
missing.py(142):     elif needs_i8_conversion(obj):
--- modulename: common, funcname: needs_i8_conversion
common.py(276):     return (is_datetime_or_timedelta_dtype(arr_or_dtype) or
--- modulename: common, funcname: is_datetime_or_timedelta_dtype
common.py(200):     tipo = _get_dtype_type(arr_or_dtype)
--- modulename: common, funcname: _get_dtype_type
common.py(369):     if isinstance(arr_or_dtype, np.dtype):
common.py(371):     elif isinstance(arr_or_dtype, type):
common.py(373):     elif isinstance(arr_or_dtype, CategoricalDtype):
common.py(375):     elif isinstance(arr_or_dtype, DatetimeTZDtype):
common.py(377):     elif isinstance(arr_or_dtype, PeriodDtype):
common.py(379):     elif isinstance(arr_or_dtype, string_types):
common.py(387):     try:
common.py(388):         return arr_or_dtype.dtype.type
common.py(201):     return issubclass(tipo, (np.datetime64, np.timedelta64))
common.py(277):             is_datetime64tz_dtype(arr_or_dtype) or
--- modulename: common, funcname: is_datetime64tz_dtype
common.py(88):     return DatetimeTZDtype.is_dtype(arr_or_dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(79):         if hasattr(dtype, 'dtype'):
dtypes.py(80):             dtype = dtype.dtype
dtypes.py(81):         if isinstance(dtype, cls):
dtypes.py(83):         elif isinstance(dtype, np.dtype):
dtypes.py(84):             return False
common.py(278):             is_period_dtype(arr_or_dtype))
--- modulename: common, funcname: is_period_dtype
common.py(97):     return PeriodDtype.is_dtype(arr_or_dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(354):         if isinstance(dtype, compat.string_types):
dtypes.py(367):         return super(PeriodDtype, cls).is_dtype(dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(79):         if hasattr(dtype, 'dtype'):
dtypes.py(80):             dtype = dtype.dtype
dtypes.py(81):         if isinstance(dtype, cls):
dtypes.py(83):         elif isinstance(dtype, np.dtype):
dtypes.py(84):             return False
missing.py(146):         result = np.isnan(values)
missing.py(149):     if isinstance(obj, ABCSeries):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(153):     return result
missing.py(119):     valid = ~invalid
missing.py(121):     if not valid.any():
--- modulename: _methods, funcname: _any
_methods.py(38):     return umr_any(a, axis, dtype, out, keepdims)
missing.py(128):     if valid.all():
--- modulename: _methods, funcname: _all
_methods.py(41):     return umr_all(a, axis, dtype, out, keepdims)
missing.py(131):     if method == 'time':
missing.py(139):     def _interp_limit(invalid, fw_limit, bw_limit):
missing.py(145):     valid_limit_directions = ['forward', 'backward', 'both']
missing.py(146):     limit_direction = limit_direction.lower()
missing.py(147):     if limit_direction not in valid_limit_directions:
missing.py(151):     from pandas import Series
missing.py(152):     ys = Series(yvalues)
--- modulename: series, funcname: __init__
series.py(140):         if fastpath:
series.py(152):             if index is not None:
series.py(155):             if data is None:
series.py(157):             if dtype is not None:
series.py(160):             if isinstance(data, MultiIndex):
series.py(163):             elif isinstance(data, Index):
series.py(170):             elif isinstance(data, np.ndarray):
series.py(171):                 pass
series.py(231):             if index is None:
series.py(232):                 if not is_list_like(data):
--- modulename: inference, funcname: is_list_like
inference.py(56):     return (hasattr(arg, '__iter__') and
inference.py(57):             not isinstance(arg, string_and_binary_types))
series.py(234):                 index = _default_index(len(data))
--- modulename: common, funcname: _default_index
common.py(228):     from pandas.core.index import RangeIndex
common.py(229):     return RangeIndex(0, n, name=None)
--- modulename: range, funcname: __new__
range.py(47):         if fastpath:
range.py(50):         cls._validate_dtype(dtype)
--- modulename: range, funcname: _validate_dtype
range.py(154):         if not (dtype is None or is_int64_dtype(dtype)):
range.py(53):         if isinstance(start, RangeIndex):
range.py(60):         def _ensure_int(value, field):
range.py(75):         if start is None and stop is None and step is None:
range.py(78):         elif start is None:
range.py(81):             start = _ensure_int(start, 'start')
--- modulename: range, funcname: _ensure_int
range.py(61):             msg = ("RangeIndex(...) must be called with integers,"
range.py(63):             if not is_scalar(value):
range.py(66):             try:
range.py(67):                 new_value = int(value)
range.py(68):                 assert(new_value == value)
range.py(73):             return new_value
range.py(82):         if stop is None:
range.py(86):             stop = _ensure_int(stop, 'stop')
--- modulename: range, funcname: _ensure_int
range.py(61):             msg = ("RangeIndex(...) must be called with integers,"
range.py(63):             if not is_scalar(value):
range.py(66):             try:
range.py(67):                 new_value = int(value)
range.py(68):                 assert(new_value == value)
range.py(73):             return new_value
range.py(87):         if step is None:
range.py(88):             step = 1
range.py(94):         return cls._simple_new(start, stop, step, name)
--- modulename: range, funcname: _simple_new
range.py(127):         result = object.__new__(cls)
range.py(130):         if start is None and stop is None:
range.py(134):         if start is None or not is_integer(start):
range.py(141):         result._start = start
range.py(142):         result._stop = stop or 0
range.py(143):         result._step = step or 1
range.py(144):         result.name = name
range.py(145):         for k, v in compat.iteritems(kwargs):
--- modulename: __init__, funcname: iteritems
__init__.py(165):         return obj.iteritems(**kw)
range.py(148):         result._reset_identity()
--- modulename: base, funcname: _reset_identity
base.py(487):         self._id = _Identity()
base.py(488):         return self
range.py(149):         return result
series.py(237):             if isinstance(data, SingleBlockManager):
series.py(243):                 data = _sanitize_array(data, index, dtype, copy,
series.py(244):                                        raise_cast_failure=True)
--- modulename: series, funcname: _sanitize_array
series.py(2835):     if dtype is not None:
series.py(2838):     if isinstance(data, ma.MaskedArray):
series.py(2846):     def _try_cast(arr, take_fast_path):
series.py(2867):     if isinstance(data, (np.ndarray, Index, Series)):
series.py(2869):         if dtype is not None:
series.py(2880):         elif isinstance(data, Index):
series.py(2887):             subarr = _try_cast(data, True)
--- modulename: series, funcname: _try_cast
series.py(2849):         if take_fast_path:
series.py(2850):             if _possibly_castable(arr) and not copy and dtype is None:
--- modulename: cast, funcname: _possibly_castable
cast.py(668):     kind = arr.dtype.kind
cast.py(669):     if kind == 'M' or kind == 'm':
cast.py(672):     return arr.dtype.name not in _POSSIBLY_CAST_DTYPES
series.py(2851):                 return arr
series.py(2889):         if copy:
series.py(2917):     def create_from_value(value, index, dtype):
series.py(2933):     if getattr(subarr, 'ndim', 0) == 0:
series.py(2952):     elif subarr.ndim == 1:
series.py(2953):         if index is not None:
series.py(2956):             if len(subarr) != len(index) and len(subarr) == 1:
--- modulename: range, funcname: __len__
range.py(462):         return max(0, -(-(self._stop - self._start) // self._step))
series.py(2968):     if issubclass(subarr.dtype.type, compat.string_types):
series.py(2971):     return subarr
series.py(246):                 data = SingleBlockManager(data, index, fastpath=True)
--- modulename: internals, funcname: __init__
internals.py(4034):         if isinstance(axis, list):
internals.py(4041):         if fastpath:
internals.py(4042):             self.axes = [axis]
internals.py(4043):             if isinstance(block, list):
internals.py(4069):         if not isinstance(block, Block):
internals.py(4070):             block = make_block(block, placement=slice(0, len(axis)), ndim=1,
--- modulename: range, funcname: __len__
range.py(462):         return max(0, -(-(self._stop - self._start) // self._step))
internals.py(4071):                                fastpath=True)
--- modulename: internals, funcname: make_block
internals.py(2652):     if klass is None:
internals.py(2653):         dtype = dtype or values.dtype
internals.py(2654):         vtype = dtype.type
internals.py(2656):         if isinstance(values, SparseArray):
internals.py(2658):         elif issubclass(vtype, np.floating):
internals.py(2659):             klass = FloatBlock
internals.py(2686):     return klass(values, ndim=ndim, fastpath=fastpath, placement=placement)
--- modulename: internals, funcname: __init__
internals.py(97):         if ndim is None:
internals.py(99):         elif values.ndim != ndim:
internals.py(101):         self.ndim = ndim
internals.py(103):         self.mgr_locs = placement
--- modulename: internals, funcname: mgr_locs
internals.py(218):         if not isinstance(new_mgr_locs, BlockPlacement):
internals.py(219):             new_mgr_locs = BlockPlacement(new_mgr_locs)
internals.py(221):         self._mgr_locs = new_mgr_locs
internals.py(104):         self.values = values
internals.py(106):         if ndim and len(self.mgr_locs) != len(self.values):
--- modulename: internals, funcname: mgr_locs
internals.py(181):         return self._mgr_locs
internals.py(4073):         self.blocks = [block]
series.py(248):         generic.NDFrame.__init__(self, data, fastpath=True)
--- modulename: generic, funcname: __init__
generic.py(117):         if not fastpath:
generic.py(127):         object.__setattr__(self, 'is_copy', None)
generic.py(128):         object.__setattr__(self, '_data', data)
generic.py(129):         object.__setattr__(self, '_item_cache', {})
series.py(250):         self.name = name
--- modulename: generic, funcname: __setattr__
generic.py(2812):         try:
generic.py(2813):             object.__getattribute__(self, name)
--- modulename: series, funcname: name
series.py(325):         return self._name
--- modulename: generic, funcname: __getattr__
generic.py(2795):         if (name in self._internal_names_set or name in self._metadata or
generic.py(2797):             return object.__getattribute__(self, name)
generic.py(2815):         except AttributeError:
generic.py(2816):             pass
generic.py(2820):         if name in self._internal_names_set:
generic.py(2822):         elif name in self._metadata:
generic.py(2823):             object.__setattr__(self, name, value)
--- modulename: series, funcname: name
series.py(329):         if value is not None and not is_hashable(value):
series.py(331):         object.__setattr__(self, '_name', value)
series.py(251):         self._set_axis(0, index, fastpath=True)
--- modulename: series, funcname: _set_axis
series.py(290):         if not fastpath:
series.py(293):         is_all_dates = labels.is_all_dates
--- modulename: numeric, funcname: is_all_dates
numeric.py(136):         return False
series.py(294):         if is_all_dates:
series.py(307):         self._set_subtyp(is_all_dates)
--- modulename: series, funcname: _set_subtyp
series.py(314):         if is_all_dates:
series.py(317):             object.__setattr__(self, '_subtyp', 'series')
series.py(309):         object.__setattr__(self, '_index', labels)
series.py(310):         if not fastpath:
missing.py(153):     start_nans = set(range(ys.first_valid_index()))
--- modulename: series, funcname: first_valid_index
series.py(2676):         if len(self) == 0:
--- modulename: series, funcname: __len__
series.py(468):         return len(self._data)
--- modulename: internals, funcname: __len__
internals.py(2953):         return len(self.items)
--- modulename: internals, funcname: _get_items
internals.py(2864):         return self.axes[0]
--- modulename: range, funcname: __len__
range.py(462):         return max(0, -(-(self._stop - self._start) // self._step))
series.py(2679):         mask = isnull(self._values)
--- modulename: series, funcname: _values
series.py(390):         return self._data.internal_values()
--- modulename: internals, funcname: internal_values
internals.py(4176):         return self._block.internal_values()
--- modulename: internals, funcname: _block
internals.py(4080):         return self.blocks[0]
--- modulename: internals, funcname: internal_values
internals.py(152):         return self.values
--- modulename: missing, funcname: isnull
missing.py(44):     return _isnull(obj)
--- modulename: missing, funcname: _isnull_new
missing.py(48):     if is_scalar(obj):
missing.py(51):     elif isinstance(obj, ABCMultiIndex):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(53):     elif isinstance(obj, (ABCSeries, np.ndarray, ABCIndexClass)):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(54):         return _isnull_ndarraylike(obj)
--- modulename: missing, funcname: _isnull_ndarraylike
missing.py(121):     values = getattr(obj, 'values', obj)
missing.py(122):     dtype = values.dtype
missing.py(124):     if is_string_dtype(dtype):
--- modulename: common, funcname: is_string_dtype
common.py(105):     dtype = _get_dtype(arr_or_dtype)
--- modulename: common, funcname: _get_dtype
common.py(345):     if isinstance(arr_or_dtype, np.dtype):
common.py(346):         return arr_or_dtype
common.py(106):     return dtype.kind in ('O', 'S', 'U') and not is_period_dtype(dtype)
missing.py(142):     elif needs_i8_conversion(obj):
--- modulename: common, funcname: needs_i8_conversion
common.py(276):     return (is_datetime_or_timedelta_dtype(arr_or_dtype) or
--- modulename: common, funcname: is_datetime_or_timedelta_dtype
common.py(200):     tipo = _get_dtype_type(arr_or_dtype)
--- modulename: common, funcname: _get_dtype_type
common.py(369):     if isinstance(arr_or_dtype, np.dtype):
common.py(371):     elif isinstance(arr_or_dtype, type):
common.py(373):     elif isinstance(arr_or_dtype, CategoricalDtype):
common.py(375):     elif isinstance(arr_or_dtype, DatetimeTZDtype):
common.py(377):     elif isinstance(arr_or_dtype, PeriodDtype):
common.py(379):     elif isinstance(arr_or_dtype, string_types):
common.py(387):     try:
common.py(388):         return arr_or_dtype.dtype.type
common.py(201):     return issubclass(tipo, (np.datetime64, np.timedelta64))
common.py(277):             is_datetime64tz_dtype(arr_or_dtype) or
--- modulename: common, funcname: is_datetime64tz_dtype
common.py(88):     return DatetimeTZDtype.is_dtype(arr_or_dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(79):         if hasattr(dtype, 'dtype'):
dtypes.py(80):             dtype = dtype.dtype
dtypes.py(81):         if isinstance(dtype, cls):
dtypes.py(83):         elif isinstance(dtype, np.dtype):
dtypes.py(84):             return False
common.py(278):             is_period_dtype(arr_or_dtype))
--- modulename: common, funcname: is_period_dtype
common.py(97):     return PeriodDtype.is_dtype(arr_or_dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(354):         if isinstance(dtype, compat.string_types):
dtypes.py(367):         return super(PeriodDtype, cls).is_dtype(dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(79):         if hasattr(dtype, 'dtype'):
dtypes.py(80):             dtype = dtype.dtype
dtypes.py(81):         if isinstance(dtype, cls):
dtypes.py(83):         elif isinstance(dtype, np.dtype):
dtypes.py(84):             return False
missing.py(146):         result = np.isnan(values)
missing.py(149):     if isinstance(obj, ABCSeries):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(153):     return result
series.py(2680):         i = mask.argmin()
series.py(2681):         if mask[i]:
series.py(2684):             return self.index[i]
--- modulename: range, funcname: __getitem__
range.py(472):         super_getitem = super(RangeIndex, self).__getitem__
range.py(474):         if is_scalar(key):
range.py(475):             n = int(key)
range.py(476):             if n != key:
range.py(478):             if n < 0:
range.py(480):             if n < 0 or n > len(self) - 1:
--- modulename: range, funcname: __len__
range.py(462):         return max(0, -(-(self._stop - self._start) // self._step))
range.py(484):             return self._start + n * self._step
missing.py(154):     end_nans = set(range(1 + ys.last_valid_index(), len(valid)))
--- modulename: series, funcname: last_valid_index
series.py(2690):         if len(self) == 0:
--- modulename: series, funcname: __len__
series.py(468):         return len(self._data)
--- modulename: internals, funcname: __len__
internals.py(2953):         return len(self.items)
--- modulename: internals, funcname: _get_items
internals.py(2864):         return self.axes[0]
--- modulename: range, funcname: __len__
range.py(462):         return max(0, -(-(self._stop - self._start) // self._step))
series.py(2693):         mask = isnull(self._values[::-1])
--- modulename: series, funcname: _values
series.py(390):         return self._data.internal_values()
--- modulename: internals, funcname: internal_values
internals.py(4176):         return self._block.internal_values()
--- modulename: internals, funcname: _block
internals.py(4080):         return self.blocks[0]
--- modulename: internals, funcname: internal_values
internals.py(152):         return self.values
--- modulename: missing, funcname: isnull
missing.py(44):     return _isnull(obj)
--- modulename: missing, funcname: _isnull_new
missing.py(48):     if is_scalar(obj):
missing.py(51):     elif isinstance(obj, ABCMultiIndex):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(53):     elif isinstance(obj, (ABCSeries, np.ndarray, ABCIndexClass)):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(54):         return _isnull_ndarraylike(obj)
--- modulename: missing, funcname: _isnull_ndarraylike
missing.py(121):     values = getattr(obj, 'values', obj)
missing.py(122):     dtype = values.dtype
missing.py(124):     if is_string_dtype(dtype):
--- modulename: common, funcname: is_string_dtype
common.py(105):     dtype = _get_dtype(arr_or_dtype)
--- modulename: common, funcname: _get_dtype
common.py(345):     if isinstance(arr_or_dtype, np.dtype):
common.py(346):         return arr_or_dtype
common.py(106):     return dtype.kind in ('O', 'S', 'U') and not is_period_dtype(dtype)
missing.py(142):     elif needs_i8_conversion(obj):
--- modulename: common, funcname: needs_i8_conversion
common.py(276):     return (is_datetime_or_timedelta_dtype(arr_or_dtype) or
--- modulename: common, funcname: is_datetime_or_timedelta_dtype
common.py(200):     tipo = _get_dtype_type(arr_or_dtype)
--- modulename: common, funcname: _get_dtype_type
common.py(369):     if isinstance(arr_or_dtype, np.dtype):
common.py(371):     elif isinstance(arr_or_dtype, type):
common.py(373):     elif isinstance(arr_or_dtype, CategoricalDtype):
common.py(375):     elif isinstance(arr_or_dtype, DatetimeTZDtype):
common.py(377):     elif isinstance(arr_or_dtype, PeriodDtype):
common.py(379):     elif isinstance(arr_or_dtype, string_types):
common.py(387):     try:
common.py(388):         return arr_or_dtype.dtype.type
common.py(201):     return issubclass(tipo, (np.datetime64, np.timedelta64))
common.py(277):             is_datetime64tz_dtype(arr_or_dtype) or
--- modulename: common, funcname: is_datetime64tz_dtype
common.py(88):     return DatetimeTZDtype.is_dtype(arr_or_dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(79):         if hasattr(dtype, 'dtype'):
dtypes.py(80):             dtype = dtype.dtype
dtypes.py(81):         if isinstance(dtype, cls):
dtypes.py(83):         elif isinstance(dtype, np.dtype):
dtypes.py(84):             return False
common.py(278):             is_period_dtype(arr_or_dtype))
--- modulename: common, funcname: is_period_dtype
common.py(97):     return PeriodDtype.is_dtype(arr_or_dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(354):         if isinstance(dtype, compat.string_types):
dtypes.py(367):         return super(PeriodDtype, cls).is_dtype(dtype)
--- modulename: dtypes, funcname: is_dtype
dtypes.py(79):         if hasattr(dtype, 'dtype'):
dtypes.py(80):             dtype = dtype.dtype
dtypes.py(81):         if isinstance(dtype, cls):
dtypes.py(83):         elif isinstance(dtype, np.dtype):
dtypes.py(84):             return False
missing.py(146):         result = np.isnan(values)
missing.py(149):     if isinstance(obj, ABCSeries):
--- modulename: generic, funcname: _check
generic.py(9):         return getattr(inst, attr, '_typ') in comp
missing.py(153):     return result
series.py(2694):         i = mask.argmin()
series.py(2695):         if mask[i]:
series.py(2698):             return self.index[len(self) - i - 1]
--- modulename: series, funcname: __len__
series.py(468):         return len(self._data)
--- modulename: internals, funcname: __len__
internals.py(2953):         return len(self.items)
--- modulename: internals, funcname: _get_items
internals.py(2864):         return self.axes[0]
--- modulename: range, funcname: __len__
range.py(462):         return max(0, -(-(self._stop - self._start) // self._step))
--- modulename: range, funcname: __getitem__
range.py(472):         super_getitem = super(RangeIndex, self).__getitem__
range.py(474):         if is_scalar(key):
range.py(475):             n = int(key)
range.py(476):             if n != key:
range.py(478):             if n < 0:
range.py(480):             if n < 0 or n > len(self) - 1:
--- modulename: range, funcname: __len__
range.py(462):         return max(0, -(-(self._stop - self._start) // self._step))
range.py(484):             return self._start + n * self._step
missing.py(170):     violate_limit = sorted(start_nans)
missing.py(172):     if limit:
missing.py(173):         if limit_direction == 'forward':
missing.py(174):             violate_limit = sorted(start_nans | set(_interp_limit(invalid,
missing.py(175):                                                                   limit, 0)))
--- modulename: missing, funcname: _interp_limit
missing.py(141):         for x in np.where(invalid)[0]:
missing.py(142):             if invalid[max(0, x - fw_limit):x + bw_limit + 1].all():
--- modulename: _methods, funcname: _all
_methods.py(41):     return umr_all(a, axis, dtype, out, keepdims)
missing.py(143):                 yield x
--- modulename: missing, funcname: _interp_limit
missing.py(141):         for x in np.where(invalid)[0]:
missing.py(176):         if limit_direction == 'backward':
missing.py(179):         if limit_direction == 'both':
missing.py(182):     xvalues = getattr(xvalues, 'values', xvalues)
missing.py(183):     yvalues = getattr(yvalues, 'values', yvalues)
missing.py(184):     result = yvalues.copy()
missing.py(186):     if method in ['linear', 'time', 'index', 'values']:
missing.py(187):         if method in ('values', 'index'):
missing.py(195):             inds = xvalues
missing.py(196):         result[invalid] = np.interp(inds[invalid], inds[valid], yvalues[valid])
--- modulename: function_base, funcname: interp
function_base.py(1668):     if period is None:
function_base.py(1669):         if isinstance(x, (float, int, number)):
function_base.py(1671):         elif isinstance(x, np.ndarray) and x.ndim == 0:
function_base.py(1674):             return compiled_interp(x, xp, fp, left, right)
missing.py(197):         result[violate_limit] = np.nan
missing.py(198):         return result
shape_base.py(93):     if isscalar(res):
--- modulename: numeric, funcname: isscalar
numeric.py(2088):     if isinstance(num, generic):
numeric.py(2091):         return type(num) in ScalarType
shape_base.py(112):         Ntot = product(outshape)
--- modulename: fromnumeric, funcname: product
fromnumeric.py(1860):     kwargs = {}
fromnumeric.py(1861):     if keepdims is not np._NoValue:
fromnumeric.py(1863):     return um.multiply.reduce(a, axis=axis, dtype=dtype, out=out, **kwargs)
shape_base.py(113):         holdshape = outshape
shape_base.py(114):         outshape = list(arr.shape)
shape_base.py(115):         outshape[axis] = len(res)
shape_base.py(116):         outarr = zeros(outshape, asarray(res).dtype)
--- modulename: numeric, funcname: asarray
numeric.py(482):     return array(a, dtype, copy=False, order=order)
shape_base.py(117):         outarr[tuple(i.tolist())] = res
shape_base.py(118):         k = 1
shape_base.py(119):         while k < Ntot:
shape_base.py(131):         return outarr
internals.py(997):         blocks = [self.make_block(interp_values, klass=self.__class__,
internals.py(998):                                   fastpath=True)]
--- modulename: internals, funcname: make_block
internals.py(195):         if placement is None:
internals.py(196):             placement = self.mgr_locs
--- modulename: internals, funcname: mgr_locs
internals.py(181):         return self._mgr_locs
internals.py(197):         if ndim is None:
internals.py(198):             ndim = self.ndim
internals.py(200):         return make_block(values, placement=placement, ndim=ndim, **kwargs)
--- modulename: internals, funcname: make_block
internals.py(2652):     if klass is None:
internals.py(2682):     elif klass is DatetimeTZBlock and not is_datetimetz(values):
internals.py(2686):     return klass(values, ndim=ndim, fastpath=fastpath, placement=placement)
--- modulename: internals, funcname: __init__
internals.py(97):         if ndim is None:
internals.py(99):         elif values.ndim != ndim:
internals.py(101):         self.ndim = ndim
internals.py(103):         self.mgr_locs = placement
--- modulename: internals, funcname: mgr_locs
internals.py(218):         if not isinstance(new_mgr_locs, BlockPlacement):
internals.py(221):         self._mgr_locs = new_mgr_locs
internals.py(104):         self.values = values
internals.py(106):         if ndim and len(self.mgr_locs) != len(self.values):
--- modulename: internals, funcname: mgr_locs
internals.py(181):         return self._mgr_locs
internals.py(999):         return self._maybe_downcast(blocks, downcast)
--- modulename: internals, funcname: _maybe_downcast
internals.py(402):         if downcast is None and self.is_float:
internals.py(403):             return blocks
internals.py(3058):             result_blocks = _extend_blocks(applied, result_blocks)
--- modulename: internals, funcname: _extend_blocks
internals.py(4553):     if blocks is None:
internals.py(4555):     if isinstance(result, list):
internals.py(4556):         for r in result:
internals.py(4557):             if isinstance(r, list):
internals.py(4560):                 blocks.append(r)
internals.py(4556):         for r in result:
internals.py(4565):     return blocks
internals.py(3042):         for b in self.blocks:
internals.py(3060):         if len(result_blocks) == 0:
internals.py(3062):         bm = self.__class__(result_blocks, axes or self.axes,
internals.py(3063):                             do_integrity_check=do_integrity_check)
--- modulename: internals, funcname: __init__
internals.py(4034):         if isinstance(axis, list):
internals.py(4035):             if len(axis) != 1:
internals.py(4038):             axis = axis[0]
internals.py(4041):         if fastpath:
internals.py(4053):             self.axes = [_ensure_index(axis)]
--- modulename: base, funcname: _ensure_index
base.py(3661):     if isinstance(index_like, Index):
base.py(3662):         if copy:
base.py(3664):         return index_like
internals.py(4056):             if isinstance(block, list):
internals.py(4059):                 if len(block) > 1:
internals.py(4064):                 if len(block) != 1:
internals.py(4067):                 block = block[0]
internals.py(4069):         if not isinstance(block, Block):
internals.py(4073):         self.blocks = [block]
internals.py(3064):         bm._consolidate_inplace()
--- modulename: internals, funcname: _consolidate_inplace
internals.py(4205):         pass
internals.py(3065):         return bm
generic.py(3754):         if inplace:
generic.py(3759):             res = self._constructor(new_data).__finalize__(self)
--- modulename: series, funcname: _constructor
series.py(266):         return Series
--- modulename: series, funcname: __init__
series.py(140):         if fastpath:
series.py(152):             if index is not None:
series.py(155):             if data is None:
series.py(157):             if dtype is not None:
series.py(160):             if isinstance(data, MultiIndex):
series.py(163):             elif isinstance(data, Index):
series.py(170):             elif isinstance(data, np.ndarray):
series.py(172):             elif isinstance(data, Series):
series.py(180):             elif isinstance(data, dict):
series.py(207):             elif isinstance(data, SingleBlockManager):
series.py(208):                 if index is None:
series.py(209):                     index = data.index
--- modulename: internals, funcname: index
internals.py(4141):         return self.axes[0]
series.py(231):             if index is None:
series.py(237):             if isinstance(data, SingleBlockManager):
series.py(238):                 if dtype is not None:
series.py(240):                 elif copy:
series.py(248):         generic.NDFrame.__init__(self, data, fastpath=True)
--- modulename: generic, funcname: __init__
generic.py(117):         if not fastpath:
generic.py(127):         object.__setattr__(self, 'is_copy', None)
generic.py(128):         object.__setattr__(self, '_data', data)
generic.py(129):         object.__setattr__(self, '_item_cache', {})
series.py(250):         self.name = name
--- modulename: generic, funcname: __setattr__
generic.py(2812):         try:
generic.py(2813):             object.__getattribute__(self, name)
--- modulename: series, funcname: name
series.py(325):         return self._name
--- modulename: generic, funcname: __getattr__
generic.py(2795):         if (name in self._internal_names_set or name in self._metadata or
generic.py(2797):             return object.__getattribute__(self, name)
generic.py(2815):         except AttributeError:
generic.py(2816):             pass
generic.py(2820):         if name in self._internal_names_set:
generic.py(2822):         elif name in self._metadata:
generic.py(2823):             object.__setattr__(self, name, value)
--- modulename: series, funcname: name
series.py(329):         if value is not None and not is_hashable(value):
series.py(331):         object.__setattr__(self, '_name', value)
series.py(251):         self._set_axis(0, index, fastpath=True)
--- modulename: series, funcname: _set_axis
series.py(290):         if not fastpath:
series.py(293):         is_all_dates = labels.is_all_dates
--- modulename: numeric, funcname: is_all_dates
numeric.py(136):         return False
series.py(294):         if is_all_dates:
series.py(307):         self._set_subtyp(is_all_dates)
--- modulename: series, funcname: _set_subtyp
series.py(314):         if is_all_dates:
series.py(317):             object.__setattr__(self, '_subtyp', 'series')
series.py(309):         object.__setattr__(self, '_index', labels)
series.py(310):         if not fastpath:
--- modulename: generic, funcname: __finalize__
generic.py(2782):         if isinstance(other, NDFrame):
generic.py(2783):             for name in self._metadata:
generic.py(2784):                 object.__setattr__(self, name, getattr(other, name, None))
--- modulename: series, funcname: name
series.py(325):         return self._name
--- modulename: series, funcname: name
series.py(329):         if value is not None and not is_hashable(value):
series.py(331):         object.__setattr__(self, '_name', value)
generic.py(2783):             for name in self._metadata:
generic.py(2785):         return self
generic.py(3760):             if axis == 1:
generic.py(3762):             return res
--- modulename: trace, funcname: _unsettrace
trace.py(80):         sys.settrace(None)

For interpolate(), it looks like limit is utilized in the _interp_limit function:

if invalid[max(0, x - fw_limit):x + bw_limit + 1].all():

For fillna(), it looks like limit is utilized in Block's fillna function: https://github.com/pandas-dev/pandas/blob/master/pandas/core/internals.py#L376

So if I've traced correctly, it doesn't appear that limit is passed through any pad function where limit < 0 should be caught.

@jreback
Copy link
Contributor

jreback commented Jan 14, 2017

can you rebase / update

@mroeschke
Copy link
Member Author

Rebasing.

As noted in my previous comment, it doesn't appear that limit gets passed through the limit<0 check here: https://github.com/pandas-dev/pandas/blob/master/pandas/src/algos_common_helper.pxi.in#L85

For interpolate, limit passes through this line:

if invalid[max(0, x - fw_limit):x + bw_limit + 1].all():

For fillna, limit passes through this line: https://github.com/pandas-dev/pandas/blob/master/pandas/core/internals.py#L378

@@ -3272,6 +3272,9 @@ def convert_objects(self, convert_dates=True, convert_numeric=False,
@Appender(_shared_docs['fillna'] % _shared_doc_kwargs)
def fillna(self, value=None, method=None, axis=None, inplace=False,
limit=None, downcast=None):
if is_integer(limit) and not limit > 0:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a) I would like these to be handled in the current cython code. b) Alternatively you can take out the check there and just put an assertion. I don't really like these types of checks being separated from the actual code, though so prefer a)

@mroeschke
Copy link
Member Author

So I discovered negative limits are caught by cython if you specifically specify the fill method to be pad:

In [3]: s.interpolate(method='pad', limit=-1)

ValueError: Limit must be non-negative

In [4]: s.fillna(method='pad', limit=-1)

ValueError: Limit must be non-negative

I am guessing this is true if the user specifies the pad or backfill variants.

Otherwise, fillna with a value specified instead of a fill method doesn't go down the cython routine and negative limit won't be caught. Should fillna be adjusted to go through the cython routine if a value is specified instead of a fill method (maybe in a new issue)? This could be done similarly with interpolate but there plenty more interpolation methods...

@mroeschke mroeschke force-pushed the fix_9217 branch 2 times, most recently from 9d6c2d2 to cfc1c92 Compare January 24, 2017 08:24
@jreback
Copy link
Contributor

jreback commented Feb 1, 2017

can you update?

@mroeschke
Copy link
Member Author

Sure thing. I will also rebase to master as well.

Circling back to my last comment, I think the assert limit > 0 is necessary in the beginning if method != pad or backfill since the other methods don't appear to go down the cython path where the limit check is made.

@jreback
Copy link
Contributor

jreback commented Feb 1, 2017

@mroeschke ideally I'd like to have these validation on args occur when they are actually used. So might need to add these checks in pandas/core/missing.py when its not going down the cython route (and then enable the cython route). OR if its easier, remove checks in cython (well maybe leave them as assert statements and put in a comment of what the guarantees), and do the validation (still in pandas.core.missing). I don't want the validation in Series/DataFrame but in the actual implementation.

@mroeschke
Copy link
Member Author

Ah I see, that makes sense. Okay I'll look into migrating the check to pandas.core.missing. Thanks!

@mroeschke
Copy link
Member Author

Migrated the limit > 0 check closer to where limit was actually used (interpolate_1d in pandas/core/missing and fillna in pandas/core/internals).

if limit:
if limit is not None:
if is_integer(limit):
assert limit > 0, ('`limit` keyword argument must be greater '
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no simply raise ValueError

@@ -372,6 +372,9 @@ def fillna(self, value, limit=None, inplace=False, downcast=None,
original_value = value
mask = isnull(self.values)
if limit is not None:
if is_integer(limit):
assert limit > 0, ('`limit` keyword argument must be greater '
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raise ValueError, or is this an actual assertion? (IOW it is checked at higher levels)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes this should be a ValueError, it's not checked at a higher level.

# related GH 9217, make sure limit is greater than 0
for limit in [-1, 0]:
s = Series([1, 2, 3, None])
tm.assertRaises(AssertionError, lambda: s.fillna(1, limit=limit))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we always raise ValueError, never AssertionError (which is an internal error and should not be user visible)

if limit:
if limit is not None:
if is_integer(limit) and limit < 1:
raise ValueError('`limit` keyword argument must be greater '
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this consistent with the cython:

raise ValueError('Limit must be non-negative')

so make the same message (you pick / combine)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is in algos_common_helper.pxi.in

@mroeschke mroeschke closed this Feb 9, 2017
@mroeschke mroeschke reopened this Feb 9, 2017
@jreback
Copy link
Contributor

jreback commented Feb 9, 2017

you need to edit the .in files, IOW algos_common.pxi.in (and not the .pxi as it says). These are not commited to the repo but generated from the .in ones.

@mroeschke
Copy link
Member Author

Ah oops, apologies. I tried editing those error messages directly through github. I'll make those changes later tonight.

add whatsnew

Add similar log to fillna

Update whatsnew with issue and fillna change

Add test for a negative limit

change if statements to assert

move limit check closer to where the variable is used

Changes assertion to ValueError
@@ -169,7 +169,9 @@ def _interp_limit(invalid, fw_limit, bw_limit):
# the beginning (see issues #9218 and #10420)
violate_limit = sorted(start_nans)

if limit:
if limit is not None:
if is_integer(limit) and limit < 1:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually I think we should make this a stronger check. limit MUST be an integer and > 0 if its not None. This would need checking both in cython and here.

@@ -83,8 +83,8 @@ def pad_{{name}}(ndarray[{{c_type}}] old, ndarray[{{c_type}}] new,
if limit is None:
lim = nright
else:
if limit < 0:
raise ValueError('Limit must be non-negative')
if limit < 1:
Copy link
Contributor

@jreback jreback Feb 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so here as well, something like

if not util.is_integer_object(limit):
    raise ValueError('limit must be an integer')
if limit < 1:
    raise ValueError(....)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alternatively you can simply remove the cython check entirely (see if anything breaks), it might not even be hitting it (and instead catching it at a higher level, IOW your new checks in missing.py), not sure.

if limit is None:
    .....
else:
    lim = int(limit)

which is will fail hard if its not an integer, and will work (incorrrectly) if its a float, so have to be careful here.

Add stricter integer check with tests
@mroeschke
Copy link
Member Author

Included int check for limit argument and added tests where floats should raise a ValueError

@jreback jreback closed this in ff0deec Feb 14, 2017
@jreback
Copy link
Contributor

jreback commented Feb 14, 2017

thanks @mroeschke

AnkurDedania pushed a commit to AnkurDedania/pandas that referenced this pull request Mar 21, 2017
…#9217)

closes pandas-dev#9217

Author: Matt Roeschke <[email protected]>

Closes pandas-dev#14994 from mroeschke/fix_9217 and squashes the following commits:

c1790ee [Matt Roeschke] Unify ValueError message and correct cython limits
6f041e6 [Matt Roeschke] Bug: Raise ValueError with interpolate limit = 0
@mroeschke mroeschke deleted the fix_9217 branch December 20, 2017 02:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Error Reporting Incorrect or improved errors from pandas Missing-data np.nan, pd.NaT, pd.NA, dropna, isnull, interpolate
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BUG/API: interpolate with limit=0 should mean no interpolation
4 participants