Skip to content

Commit

Permalink
DEPR: Add deprecation warning for factorize() order keyword (pandas-d…
Browse files Browse the repository at this point in the history
  • Loading branch information
EricChea authored and harisbal committed Feb 28, 2018
1 parent 7077fe9 commit e7e1712
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 2 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.23.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,7 @@ Deprecations

- The ``broadcast`` parameter of ``.apply()`` is deprecated in favor of ``result_type='broadcast'`` (:issue:`18577`)
- The ``reduce`` parameter of ``.apply()`` is deprecated in favor of ``result_type='reduce'`` (:issue:`18577`)
- The ``order`` parameter of :func:`factorize` is deprecated and will be removed in a future release (:issue:`19727`)

.. _whatsnew_0230.prior_deprecations:

Expand Down
2 changes: 2 additions & 0 deletions pandas/core/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from pandas.core import common as com
from pandas._libs import algos, lib, hashtable as htable
from pandas._libs.tslib import iNaT
from pandas.util._decorators import deprecate_kwarg


# --------------- #
Expand Down Expand Up @@ -436,6 +437,7 @@ def isin(comps, values):
return f(comps, values)


@deprecate_kwarg(old_arg_name='order', new_arg_name=None)
def factorize(values, sort=False, order=None, na_sentinel=-1, size_hint=None):
"""
Encode input values as an enumerated type or categorical variable
Expand Down
9 changes: 9 additions & 0 deletions pandas/tests/test_algos.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,15 @@ def test_uint64_factorize(self):
tm.assert_numpy_array_equal(labels, exp_labels)
tm.assert_numpy_array_equal(uniques, exp_uniques)

def test_deprecate_order(self):
# gh 19727 - check warning is raised for deprecated keyword, order.
# Test not valid once order keyword is removed.
data = np.array([2**63, 1, 2**63], dtype=np.uint64)
with tm.assert_produces_warning(expected_warning=FutureWarning):
algos.factorize(data, order=True)
with tm.assert_produces_warning(False):
algos.factorize(data)


class TestUnique(object):

Expand Down
14 changes: 14 additions & 0 deletions pandas/tests/util/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ def _f2(new=False):
def _f3(new=0):
return new

@deprecate_kwarg('old', None)
def _f4(old=True, unchanged=True):
return old

self.f1 = _f1
self.f2 = _f2
self.f3 = _f3
self.f4 = _f4

def test_deprecate_kwarg(self):
x = 78
Expand Down Expand Up @@ -72,6 +77,15 @@ def test_bad_deprecate_kwarg(self):
def f4(new=None):
pass

def test_deprecate_keyword(self):
x = 9
with tm.assert_produces_warning(FutureWarning):
result = self.f4(old=x)
assert result is x
with tm.assert_produces_warning(None):
result = self.f4(unchanged=x)
assert result is True


def test_rands():
r = tm.rands(10)
Expand Down
38 changes: 36 additions & 2 deletions pandas/util/_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ def deprecate_kwarg(old_arg_name, new_arg_name, mapping=None, stacklevel=2):
----------
old_arg_name : str
Name of argument in function to deprecate
new_arg_name : str
Name of preferred argument in function
new_arg_name : str or None
Name of preferred argument in function. Use None to raise warning that
``old_arg_name`` keyword is deprecated.
mapping : dict or callable
If mapping is present, use it to translate old arguments to
new arguments. A callable must do its own value checking;
Expand All @@ -82,12 +83,15 @@ def deprecate_kwarg(old_arg_name, new_arg_name, mapping=None, stacklevel=2):
...
>>> f(columns='should work ok')
should work ok
>>> f(cols='should raise warning')
FutureWarning: cols is deprecated, use columns instead
warnings.warn(msg, FutureWarning)
should raise warning
>>> f(cols='should error', columns="can\'t pass do both")
TypeError: Can only specify 'cols' or 'columns', not both
>>> @deprecate_kwarg('old', 'new', {'yes': True, 'no': False})
... def f(new=False):
... print('yes!' if new else 'no!')
Expand All @@ -96,6 +100,25 @@ def deprecate_kwarg(old_arg_name, new_arg_name, mapping=None, stacklevel=2):
FutureWarning: old='yes' is deprecated, use new=True instead
warnings.warn(msg, FutureWarning)
yes!
To raise a warning that a keyword will be removed entirely in the future
>>> @deprecate_kwarg(old_arg_name='cols', new_arg_name=None)
... def f(cols='', another_param=''):
... print(cols)
...
>>> f(cols='should raise warning')
FutureWarning: the 'cols' keyword is deprecated and will be removed in a
future version please takes steps to stop use of 'cols'
should raise warning
>>> f(another_param='should not raise warning')
should not raise warning
>>> f(cols='should raise warning', another_param='')
FutureWarning: the 'cols' keyword is deprecated and will be removed in a
future version please takes steps to stop use of 'cols'
should raise warning
"""

if mapping is not None and not hasattr(mapping, 'get') and \
Expand All @@ -107,6 +130,17 @@ def _deprecate_kwarg(func):
@wraps(func)
def wrapper(*args, **kwargs):
old_arg_value = kwargs.pop(old_arg_name, None)

if new_arg_name is None and old_arg_value is not None:
msg = (
"the '{old_name}' keyword is deprecated and will be "
"removed in a future version "
"please takes steps to stop use of '{old_name}'"
).format(old_name=old_arg_name)
warnings.warn(msg, FutureWarning, stacklevel=stacklevel)
kwargs[old_arg_name] = old_arg_value
return func(*args, **kwargs)

if old_arg_value is not None:
if mapping is not None:
if hasattr(mapping, 'get'):
Expand Down

0 comments on commit e7e1712

Please sign in to comment.