Skip to content

Commit

Permalink
DEPR: deprecate raise_on_error in .where/.mask in favor of errors=
Browse files Browse the repository at this point in the history
closes #14968
  • Loading branch information
jreback committed Oct 5, 2017
1 parent 6b29fc0 commit 9a68746
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 68 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.21.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,7 @@ Deprecations
- ``cdate_range`` has been deprecated in favor of :func:`bdate_range`, which has gained ``weekmask`` and ``holidays`` parameters for building custom frequency date ranges. See the :ref:`documentation <timeseries.custom-freq-ranges>` for more details (:issue:`17596`)
- passing ``categories`` or ``ordered`` kwargs to :func:`Series.astype` is deprecated, in favor of passing a :ref:`CategoricalDtype <whatsnew_0210.enhancements.categorical_dtype>` (:issue:`17636`)
- Passing a non-existant column in ``.to_excel(..., columns=)`` is deprecated and will raise a ``KeyError`` in the future (:issue:`17295`)
- ``raise_on_error`` parameter to :func:`Series.where`, :func:`Series.mask`, :func:`DataFrame.where`, :func:`DataFrame.mask` is deprecated, in favor of ``errors=`` (:issue:`14968`)

.. _whatsnew_0210.deprecations.select:

Expand Down
38 changes: 14 additions & 24 deletions pandas/core/computation/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def set_numexpr_threads(n=None):
ne.set_num_threads(n)


def _evaluate_standard(op, op_str, a, b, raise_on_error=True, **eval_kwargs):
def _evaluate_standard(op, op_str, a, b, **eval_kwargs):
""" standard evaluation """
if _TEST_MODE:
_store_test_result(False)
Expand Down Expand Up @@ -89,7 +89,7 @@ def _can_use_numexpr(op, op_str, a, b, dtype_check):
return False


def _evaluate_numexpr(op, op_str, a, b, raise_on_error=False, truediv=True,
def _evaluate_numexpr(op, op_str, a, b, truediv=True,
reversed=False, **eval_kwargs):
result = None

Expand All @@ -111,25 +111,22 @@ def _evaluate_numexpr(op, op_str, a, b, raise_on_error=False, truediv=True,
except ValueError as detail:
if 'unknown type object' in str(detail):
pass
except Exception as detail:
if raise_on_error:
raise

if _TEST_MODE:
_store_test_result(result is not None)

if result is None:
result = _evaluate_standard(op, op_str, a, b, raise_on_error)
result = _evaluate_standard(op, op_str, a, b)

return result


def _where_standard(cond, a, b, raise_on_error=True):
def _where_standard(cond, a, b):
return np.where(_values_from_object(cond), _values_from_object(a),
_values_from_object(b))


def _where_numexpr(cond, a, b, raise_on_error=False):
def _where_numexpr(cond, a, b):
result = None

if _can_use_numexpr(None, 'where', a, b, 'where'):
Expand All @@ -147,11 +144,10 @@ def _where_numexpr(cond, a, b, raise_on_error=False):
if 'unknown type object' in str(detail):
pass
except Exception as detail:
if raise_on_error:
raise TypeError(str(detail))
raise TypeError(str(detail))

if result is None:
result = _where_standard(cond, a, b, raise_on_error)
result = _where_standard(cond, a, b)

return result

Expand Down Expand Up @@ -189,7 +185,7 @@ def _bool_arith_check(op_str, a, b, not_allowed=frozenset(('/', '//', '**')),
return True


def evaluate(op, op_str, a, b, raise_on_error=False, use_numexpr=True,
def evaluate(op, op_str, a, b, use_numexpr=True,
**eval_kwargs):
""" evaluate and return the expression of the op on a and b
Expand All @@ -200,19 +196,16 @@ def evaluate(op, op_str, a, b, raise_on_error=False, use_numexpr=True,
op_str: the string version of the op
a : left operand
b : right operand
raise_on_error : pass the error to the higher level if indicated
(default is False), otherwise evaluate the op with and
return the results
use_numexpr : whether to try to use numexpr (default True)
"""

use_numexpr = use_numexpr and _bool_arith_check(op_str, a, b)
if use_numexpr:
return _evaluate(op, op_str, a, b, raise_on_error=raise_on_error,
**eval_kwargs)
return _evaluate_standard(op, op_str, a, b, raise_on_error=raise_on_error)
return _evaluate(op, op_str, a, b, **eval_kwargs)
return _evaluate_standard(op, op_str, a, b)


def where(cond, a, b, raise_on_error=False, use_numexpr=True):
def where(cond, a, b, use_numexpr=True):
""" evaluate the where condition cond on a and b
Parameters
Expand All @@ -221,15 +214,12 @@ def where(cond, a, b, raise_on_error=False, use_numexpr=True):
cond : a boolean array
a : return if cond is True
b : return if cond is False
raise_on_error : pass the error to the higher level if indicated
(default is False), otherwise evaluate the op with and
return the results
use_numexpr : whether to try to use numexpr (default True)
"""

if use_numexpr:
return _where(cond, a, b, raise_on_error=raise_on_error)
return _where_standard(cond, a, b, raise_on_error=raise_on_error)
return _where(cond, a, b)
return _where_standard(cond, a, b)


def set_test_mode(v=True):
Expand Down
10 changes: 4 additions & 6 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -3836,9 +3836,9 @@ def _combine_match_columns(self, other, func, level=None,
try_cast=try_cast)
return self._constructor(new_data)

def _combine_const(self, other, func, raise_on_error=True, try_cast=True):
def _combine_const(self, other, func, errors='raise', try_cast=True):
new_data = self._data.eval(func=func, other=other,
raise_on_error=raise_on_error,
errors=errors,
try_cast=try_cast)
return self._constructor(new_data)

Expand Down Expand Up @@ -4009,8 +4009,7 @@ def combiner(x, y, needs_i8_conversion=False):
else:
mask = isna(x_values)

return expressions.where(mask, y_values, x_values,
raise_on_error=True)
return expressions.where(mask, y_values, x_values)

return self.combine(other, combiner, overwrite=False)

Expand Down Expand Up @@ -4065,8 +4064,7 @@ def update(self, other, join='left', overwrite=True, filter_func=None,
if mask.all():
continue

self[col] = expressions.where(mask, this, that,
raise_on_error=True)
self[col] = expressions.where(mask, this, that)

# ----------------------------------------------------------------------
# Misc methods
Expand Down
45 changes: 38 additions & 7 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -5758,7 +5758,7 @@ def _align_series(self, other, join='outer', axis=None, level=None,
return left.__finalize__(self), right.__finalize__(other)

def _where(self, cond, other=np.nan, inplace=False, axis=None, level=None,
try_cast=False, raise_on_error=True):
errors='raise', try_cast=False):
"""
Equivalent to public method `where`, except that `other` is not
applied as a function even if callable. Used in __setitem__.
Expand Down Expand Up @@ -5887,7 +5887,7 @@ def _where(self, cond, other=np.nan, inplace=False, axis=None, level=None,

else:
new_data = self._data.where(other=other, cond=cond, align=align,
raise_on_error=raise_on_error,
errors=errors,
try_cast=try_cast, axis=block_axis,
transpose=self._AXIS_REVERSED)

Expand Down Expand Up @@ -5924,12 +5924,21 @@ def _where(self, cond, other=np.nan, inplace=False, axis=None, level=None,
Whether to perform the operation in place on the data
axis : alignment axis if needed, default None
level : alignment level if needed, default None
errors : str, {'raise', 'ignore'}, default 'raise'
- ``raise`` : allow exceptions to be raised
- ``ignore`` : suppress exceptions. On error return original object
Note that currently this parameter won't affect
the results and will always coerce to a suitable dtype.
try_cast : boolean, default False
try to cast the result back to the input type (if possible),
raise_on_error : boolean, default True
Whether to raise on invalid data types (e.g. trying to where on
strings)
.. deprecated:: 0.21.0
Returns
-------
wh : same type as caller
Expand Down Expand Up @@ -6005,24 +6014,46 @@ def _where(self, cond, other=np.nan, inplace=False, axis=None, level=None,
cond_rev="False", name='where',
name_other='mask'))
def where(self, cond, other=np.nan, inplace=False, axis=None, level=None,
try_cast=False, raise_on_error=True):
errors='raise', try_cast=False, raise_on_error=None):

if raise_on_error is not None:
warnings.warn(
"raise_on_error is deprecated in "
"favor of errors='raise|ignore'",
FutureWarning, stacklevel=2)

if raise_on_error:
errors = 'raise'
else:
errors = 'ignore'

other = com._apply_if_callable(other, self)
return self._where(cond, other, inplace, axis, level, try_cast,
raise_on_error)
return self._where(cond, other, inplace, axis, level,
errors=errors, try_cast=try_cast)

@Appender(_shared_docs['where'] % dict(_shared_doc_kwargs, cond="False",
cond_rev="True", name='mask',
name_other='where'))
def mask(self, cond, other=np.nan, inplace=False, axis=None, level=None,
try_cast=False, raise_on_error=True):
errors='raise', try_cast=False, raise_on_error=None):

if raise_on_error is not None:
warnings.warn(
"raise_on_error is deprecated in "
"favor of errors='raise|ignore'",
FutureWarning, stacklevel=2)

if raise_on_error:
errors = 'raise'
else:
errors = 'ignore'

inplace = validate_bool_kwarg(inplace, 'inplace')
cond = com._apply_if_callable(cond, self)

return self.where(~cond, other=other, inplace=inplace, axis=axis,
level=level, try_cast=try_cast,
raise_on_error=raise_on_error)
errors=errors)

_shared_docs['shift'] = ("""
Shift index by desired number of periods with an optional time freq
Expand Down
43 changes: 27 additions & 16 deletions pandas/core/internals.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,10 +532,16 @@ def astype(self, dtype, copy=False, errors='raise', values=None, **kwargs):
**kwargs)

def _astype(self, dtype, copy=False, errors='raise', values=None,
klass=None, mgr=None, raise_on_error=False, **kwargs):
klass=None, mgr=None, **kwargs):
"""
Coerce to the new type (if copy=True, return a new copy)
raise on an except if raise == True
Coerce to the new type
dtype : str, dtype convertible
copy : boolean, default False
copy if indicated
errors : str, {'raise', 'ignore'}, default 'ignore'
- ``raise`` : allow exceptions to be raised
- ``ignore`` : suppress exceptions. On error return original object
"""
errors_legal_values = ('raise', 'ignore')

Expand Down Expand Up @@ -1248,16 +1254,18 @@ def shift(self, periods, axis=0, mgr=None):

return [self.make_block(new_values, fastpath=True)]

def eval(self, func, other, raise_on_error=True, try_cast=False, mgr=None):
def eval(self, func, other, errors='raise', try_cast=False, mgr=None):
"""
evaluate the block; return result block from the result
Parameters
----------
func : how to combine self, other
other : a ndarray/object
raise_on_error : if True, raise when I can't perform the function,
False by default (and just return the data that we had coming in)
errors : str, {'raise', 'ignore'}, default 'raise'
- ``raise`` : allow exceptions to be raised
- ``ignore`` : suppress exceptions. On error return original object
try_cast : try casting the results to the input type
Returns
Expand Down Expand Up @@ -1295,7 +1303,7 @@ def eval(self, func, other, raise_on_error=True, try_cast=False, mgr=None):
except TypeError:
block = self.coerce_to_target_dtype(orig_other)
return block.eval(func, orig_other,
raise_on_error=raise_on_error,
errors=errors,
try_cast=try_cast, mgr=mgr)

# get the result, may need to transpose the other
Expand Down Expand Up @@ -1337,7 +1345,7 @@ def get_result(other):
# error handler if we have an issue operating with the function
def handle_error():

if raise_on_error:
if errors == 'raise':
# The 'detail' variable is defined in outer scope.
raise TypeError('Could not operate %s with block values %s' %
(repr(other), str(detail))) # noqa
Expand Down Expand Up @@ -1383,7 +1391,7 @@ def handle_error():
result = _block_shape(result, ndim=self.ndim)
return [self.make_block(result, fastpath=True, )]

def where(self, other, cond, align=True, raise_on_error=True,
def where(self, other, cond, align=True, errors='raise',
try_cast=False, axis=0, transpose=False, mgr=None):
"""
evaluate the block; return result block(s) from the result
Expand All @@ -1393,8 +1401,10 @@ def where(self, other, cond, align=True, raise_on_error=True,
other : a ndarray/object
cond : the condition to respect
align : boolean, perform alignment on other/cond
raise_on_error : if True, raise when I can't perform the function,
False by default (and just return the data that we had coming in)
errors : str, {'raise', 'ignore'}, default 'raise'
- ``raise`` : allow exceptions to be raised
- ``ignore`` : suppress exceptions. On error return original object
axis : int
transpose : boolean
Set to True if self is stored with axes reversed
Expand All @@ -1404,6 +1414,7 @@ def where(self, other, cond, align=True, raise_on_error=True,
a new block(s), the result of the func
"""
import pandas.core.computation.expressions as expressions
assert errors in ['raise', 'ignore']

values = self.values
orig_other = other
Expand Down Expand Up @@ -1436,9 +1447,9 @@ def func(cond, values, other):

try:
return self._try_coerce_result(expressions.where(
cond, values, other, raise_on_error=True))
cond, values, other))
except Exception as detail:
if raise_on_error:
if errors == 'raise':
raise TypeError('Could not operate [%s] with block values '
'[%s]' % (repr(other), str(detail)))
else:
Expand All @@ -1454,10 +1465,10 @@ def func(cond, values, other):
except TypeError:

# we cannot coerce, return a compat dtype
# we are explicity ignoring raise_on_error here
# we are explicity ignoring errors
block = self.coerce_to_target_dtype(other)
blocks = block.where(orig_other, cond, align=align,
raise_on_error=raise_on_error,
errors=errors,
try_cast=try_cast, axis=axis,
transpose=transpose)
return self._maybe_downcast(blocks, 'infer')
Expand Down Expand Up @@ -2745,7 +2756,7 @@ def sp_index(self):
def kind(self):
return self.values.kind

def _astype(self, dtype, copy=False, raise_on_error=True, values=None,
def _astype(self, dtype, copy=False, errors='raise', values=None,
klass=None, mgr=None, **kwargs):
if values is None:
values = self.values
Expand Down
Loading

0 comments on commit 9a68746

Please sign in to comment.