From 676bb5066536cdf758b4a01611e1dc2cd51a3b2e Mon Sep 17 00:00:00 2001 From: Lucas Kushner Date: Sat, 15 Jul 2017 19:28:56 +0000 Subject: [PATCH 01/12] Deprecating Series.argmin and Series.argmax (#16830) Added statements about correcting behavior in future commit Add reference to github ticket Fixing placement of github comment Made test code more explicit Fixing unrelated tests that are also throwing warnings Updating whatsnew to give more detail about deprecation Fixing whatsnew and breaking out tests to catch warnings Additional comments and more concise whatsnew Updating deprecate decorator to support custom message DOC: Update docstrings, depr message, and whatsnew --- doc/source/whatsnew/v0.21.0.txt | 25 +++++++++++- pandas/core/series.py | 29 +++++++++---- pandas/tests/series/test_analytics.py | 59 ++++++++++++++++++++------- pandas/tests/series/test_api.py | 2 +- pandas/tests/sparse/test_series.py | 12 +++++- pandas/util/_decorators.py | 8 ++-- 6 files changed, 107 insertions(+), 28 deletions(-) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index ecea931960b6a..584a89bc1ef12 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -439,12 +439,35 @@ Other API Changes Deprecations ~~~~~~~~~~~~ -- :func:`read_excel()` has deprecated ``sheetname`` in favor of ``sheet_name`` for consistency with ``.to_excel()`` (:issue:`10559`). +- :func:`read_excel()` has deprecated ``sheetname`` in favor of ``sheet_name`` for consistency with ``.to_excel()`` (:issue:`10559`). - ``pd.options.html.border`` has been deprecated in favor of ``pd.options.display.html.border`` (:issue:`15793`). - :func:`SeriesGroupBy.nth` has deprecated ``True`` in favor of ``'all'`` for its kwarg ``dropna`` (:issue:`11038`). +Series.argmax and Series.argmin +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- The behavior of :func:`Series.argmax` has been deprecated in favor of :func:`Series.idxmax` (:issue:`16830`) +- The behavior of :func:`Series.argmin` has been deprecated in favor of :func:`Series.idxmin` (:issue:`16830`) + +For compatibility with NumPy arrays, ``pd.Series`` implements ``argmax`` and +``argmin``. Since pandas 0.13 :func:`Series.argmax` and +:func:`Series.argmin` returned the *label* of the maximum and minimum, +rather than the *position*. + +Since returning the positional ``argmax`` and ``argmin`` can be useful, +we've deprecated the current behavior of :func:`Series.argmax` and +:func:`Series.argmin`. Using either of these will emit a ``FutureWarning``. + +If you were using ``Series.argmin`` and ``Series.argmax``, please switch to using +``idxmin`` and ``idxmax``. In the future, ``Series.argmin`` will return the +*position* of the minimum. Likewise for ``Series.argmax``. + +Until this functionality is implemented in the future, we recommend using +``Series.values.argmin()`` and ``Series.values.argmax()`` for returning +the positional ``argmin`` and ``argmax``. + .. _whatsnew_0210.prior_deprecations: Removal of prior version deprecations/changes diff --git a/pandas/core/series.py b/pandas/core/series.py index ac11c5f908fdc..a0b7bfeb46318 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -68,7 +68,8 @@ import pandas.core.common as com import pandas.core.nanops as nanops import pandas.io.formats.format as fmt -from pandas.util._decorators import Appender, deprecate_kwarg, Substitution +from pandas.util._decorators import ( + Appender, deprecate, deprecate_kwarg, Substitution) from pandas.util._validators import validate_bool_kwarg from pandas._libs import index as libindex, tslib as libts, lib, iNaT @@ -1271,7 +1272,7 @@ def duplicated(self, keep='first'): def idxmin(self, axis=None, skipna=True, *args, **kwargs): """ - Index of first occurrence of minimum of values. + Index *label* of the first occurrence of minimum of values. Parameters ---------- @@ -1284,7 +1285,9 @@ def idxmin(self, axis=None, skipna=True, *args, **kwargs): Notes ----- - This method is the Series version of ``ndarray.argmin``. + This method is the Series version of ``ndarray.argmin``. This method + returns the label of the minimum, while ``ndarray.argmin`` returns + the position. To get the position, use ``series.values.argmin()``. See Also -------- @@ -1299,7 +1302,7 @@ def idxmin(self, axis=None, skipna=True, *args, **kwargs): def idxmax(self, axis=None, skipna=True, *args, **kwargs): """ - Index of first occurrence of maximum of values. + Index *label* of the first occurrence of maximum of values. Parameters ---------- @@ -1312,7 +1315,9 @@ def idxmax(self, axis=None, skipna=True, *args, **kwargs): Notes ----- - This method is the Series version of ``ndarray.argmax``. + This method is the Series version of ``ndarray.argmax``. This method + returns the label of the maximum, while ``ndarray.argmax`` returns + the position. To get the position, use ``series.values.argmax()``. See Also -------- @@ -1326,8 +1331,18 @@ def idxmax(self, axis=None, skipna=True, *args, **kwargs): return self.index[i] # ndarray compat - argmin = idxmin - argmax = idxmax + argmin = deprecate('argmin', idxmin, + msg="'argmin' is deprecated. Use 'idxmin' instead. " + "The behavior of 'argmin' will be corrected to " + "return the positional minimum in the future. " + "Use 'series.values.argmin' to get the position of " + "the minimum now.") + argmax = deprecate('argmax', idxmax, + msg="'argmax' is deprecated. Use 'idxmax' instead. " + "The behavior of 'argmax' will be corrected to " + "return the positional maximum in the future. " + "Use 'series.values.argmax' to get the position of " + "the maximum now.") def round(self, decimals=0, *args, **kwargs): """ diff --git a/pandas/tests/series/test_analytics.py b/pandas/tests/series/test_analytics.py index f1d044f7a1132..63a5b90e5e047 100644 --- a/pandas/tests/series/test_analytics.py +++ b/pandas/tests/series/test_analytics.py @@ -1242,16 +1242,31 @@ def test_idxmin(self): result = s.idxmin() assert result == 1 - def test_numpy_argmin(self): - # argmin is aliased to idxmin + def test_numpy_argmin_deprecated(self): + # See gh-16830 data = np.random.randint(0, 11, size=10) - result = np.argmin(Series(data)) - assert result == np.argmin(data) + + s = Series(data) + with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + # The deprecation of Series.argmin also causes a deprecation + # warning when calling np.argmin. This behavior is temporary + # until the implemention of Series.argmin is corrected. + result = np.argmin(s) + expected = np.argmin(data) + assert result == expected + + with tm.assert_produces_warning(FutureWarning): + # argmin is aliased to idxmin + result = s.argmin() + expected = s.idxmin() + assert result == expected if not _np_version_under1p10: - msg = "the 'out' parameter is not supported" - tm.assert_raises_regex(ValueError, msg, np.argmin, - Series(data), out=data) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + msg = "the 'out' parameter is not supported" + tm.assert_raises_regex(ValueError, msg, np.argmin, + s, out=data) def test_idxmax(self): # test idxmax @@ -1297,17 +1312,31 @@ def test_idxmax(self): result = s.idxmin() assert result == 1.1 - def test_numpy_argmax(self): - - # argmax is aliased to idxmax + def test_numpy_argmax_deprecated(self): + # See gh-16830 data = np.random.randint(0, 11, size=10) - result = np.argmax(Series(data)) - assert result == np.argmax(data) + + s = Series(data) + with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + # The deprecation of Series.argmax also causes a deprecation + # warning when calling np.argmax. This behavior is temporary + # until the implemention of Series.argmax is corrected. + result = np.argmax(s) + expected = np.argmax(data) + assert result == expected + + with tm.assert_produces_warning(FutureWarning): + # argmax is aliased to idxmax + result = s.argmax() + expected = s.idxmax() + assert result == expected if not _np_version_under1p10: - msg = "the 'out' parameter is not supported" - tm.assert_raises_regex(ValueError, msg, np.argmax, - Series(data), out=data) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + msg = "the 'out' parameter is not supported" + tm.assert_raises_regex(ValueError, msg, np.argmax, + s, out=data) def test_ptp(self): N = 1000 diff --git a/pandas/tests/series/test_api.py b/pandas/tests/series/test_api.py index d0805e2bb54d2..26a0078efd35d 100644 --- a/pandas/tests/series/test_api.py +++ b/pandas/tests/series/test_api.py @@ -345,7 +345,7 @@ def test_ndarray_compat(self): index=date_range('1/1/2000', periods=1000)) def f(x): - return x[x.argmax()] + return x[x.idxmax()] result = tsdf.apply(f) expected = tsdf.max() diff --git a/pandas/tests/sparse/test_series.py b/pandas/tests/sparse/test_series.py index b44314d4e733b..b19bc2944a93f 100644 --- a/pandas/tests/sparse/test_series.py +++ b/pandas/tests/sparse/test_series.py @@ -1379,11 +1379,21 @@ def test_numpy_func_call(self): # numpy passes in 'axis=None' or `axis=-1' funcs = ['sum', 'cumsum', 'var', 'mean', 'prod', 'cumprod', 'std', 'argsort', - 'argmin', 'argmax', 'min', 'max'] + 'min', 'max'] for func in funcs: for series in ('bseries', 'zbseries'): getattr(np, func)(getattr(self, series)) + def test_deprecated_numpy_func_call(self): + # NOTE: These should be add to the 'test_numpy_func_call' test above + # once the behavior of argmin/argmax is corrected. + funcs = ['argmin', 'argmax'] + for func in funcs: + for series in ('bseries', 'zbseries'): + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + getattr(np, func)(getattr(self, series)) + @pytest.mark.parametrize( 'datetime_type', (np.datetime64, diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index bb7ffe45c689b..c491f7cee9e1c 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -7,7 +7,7 @@ def deprecate(name, alternative, alt_name=None, klass=None, - stacklevel=2): + stacklevel=2, msg=None): """ Return a new function that emits a deprecation warning on use. @@ -21,14 +21,16 @@ def deprecate(name, alternative, alt_name=None, klass=None, Name to use in preference of alternative.__name__ klass : Warning, default FutureWarning stacklevel : int, default 2 + msg : str + The message to display in the warning. + Default is '{name} is deprecated. Use {alt_name} instead.' """ alt_name = alt_name or alternative.__name__ klass = klass or FutureWarning + msg = msg or "{} is deprecated. Use {} instead".format(name, alt_name) def wrapper(*args, **kwargs): - msg = "{name} is deprecated. Use {alt_name} instead".format( - name=name, alt_name=alt_name) warnings.warn(msg, klass, stacklevel=stacklevel) return alternative(*args, **kwargs) return wrapper From 578dbd57fced8cdf536310a3d09a37d7341e846b Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Wed, 20 Sep 2017 06:00:08 -0500 Subject: [PATCH 02/12] Added debug prints --- pandas/tests/sparse/test_series.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pandas/tests/sparse/test_series.py b/pandas/tests/sparse/test_series.py index b19bc2944a93f..3f1ad8eaec538 100644 --- a/pandas/tests/sparse/test_series.py +++ b/pandas/tests/sparse/test_series.py @@ -1388,12 +1388,24 @@ def test_deprecated_numpy_func_call(self): # NOTE: These should be add to the 'test_numpy_func_call' test above # once the behavior of argmin/argmax is corrected. funcs = ['argmin', 'argmax'] + import warnings + print("before") + print("filters", warnings.filters) + print("onceregsitry", warnings.onceregistry) for func in funcs: for series in ('bseries', 'zbseries'): with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + print("during") + print("filters", warnings.filters) + print("onceregsitry", warnings.onceregistry) + getattr(np, func)(getattr(self, series)) + print("after") + print("filters", warnings.filters) + print("onceregsitry", warnings.onceregistry) + @pytest.mark.parametrize( 'datetime_type', (np.datetime64, From 4c770b64fdccf403991044f017f691238dec200a Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Wed, 20 Sep 2017 08:57:37 -0500 Subject: [PATCH 03/12] Try splitting the filters --- pandas/tests/series/test_analytics.py | 20 +++++++++++--------- pandas/tests/sparse/test_series.py | 18 +++++------------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/pandas/tests/series/test_analytics.py b/pandas/tests/series/test_analytics.py index 63a5b90e5e047..de680a6f0593f 100644 --- a/pandas/tests/series/test_analytics.py +++ b/pandas/tests/series/test_analytics.py @@ -1244,7 +1244,7 @@ def test_idxmin(self): def test_numpy_argmin_deprecated(self): # See gh-16830 - data = np.random.randint(0, 11, size=10) + data = np.arange(10) s = Series(data) with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): @@ -1252,14 +1252,15 @@ def test_numpy_argmin_deprecated(self): # warning when calling np.argmin. This behavior is temporary # until the implemention of Series.argmin is corrected. result = np.argmin(s) - expected = np.argmin(data) - assert result == expected + + assert result == 0 with tm.assert_produces_warning(FutureWarning): # argmin is aliased to idxmin result = s.argmin() - expected = s.idxmin() - assert result == expected + + expected = s.idxmin() + assert result == expected if not _np_version_under1p10: with tm.assert_produces_warning(FutureWarning, @@ -1315,6 +1316,7 @@ def test_idxmax(self): def test_numpy_argmax_deprecated(self): # See gh-16830 data = np.random.randint(0, 11, size=10) + data = np.arange(10) s = Series(data) with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): @@ -1322,14 +1324,14 @@ def test_numpy_argmax_deprecated(self): # warning when calling np.argmax. This behavior is temporary # until the implemention of Series.argmax is corrected. result = np.argmax(s) - expected = np.argmax(data) - assert result == expected + assert result == 9 with tm.assert_produces_warning(FutureWarning): # argmax is aliased to idxmax result = s.argmax() - expected = s.idxmax() - assert result == expected + + expected = s.idxmax() + assert result == expected if not _np_version_under1p10: with tm.assert_produces_warning(FutureWarning, diff --git a/pandas/tests/sparse/test_series.py b/pandas/tests/sparse/test_series.py index 3f1ad8eaec538..b247c595da0fe 100644 --- a/pandas/tests/sparse/test_series.py +++ b/pandas/tests/sparse/test_series.py @@ -1,6 +1,7 @@ # pylint: disable-msg=E1101,W0612 import operator +import warnings from datetime import datetime import pytest @@ -1388,23 +1389,14 @@ def test_deprecated_numpy_func_call(self): # NOTE: These should be add to the 'test_numpy_func_call' test above # once the behavior of argmin/argmax is corrected. funcs = ['argmin', 'argmax'] - import warnings - print("before") - print("filters", warnings.filters) - print("onceregsitry", warnings.onceregistry) for func in funcs: for series in ('bseries', 'zbseries'): - with tm.assert_produces_warning(FutureWarning, - check_stacklevel=False): - print("during") - print("filters", warnings.filters) - print("onceregsitry", warnings.onceregistry) - + with warnings.catch_warnings(): + warnings.simplefilter("ignore") getattr(np, func)(getattr(self, series)) - print("after") - print("filters", warnings.filters) - print("onceregsitry", warnings.onceregistry) + with tm.assert_produces_warning(FutureWarning): + getattr(getattr(self, series), func)() @pytest.mark.parametrize( From 0e039de017967354c9f6afb34c2e70669729f2ff Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Sun, 24 Sep 2017 07:09:16 -0500 Subject: [PATCH 04/12] Reword whatsnew --- doc/source/whatsnew/v0.21.0.txt | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index 584a89bc1ef12..d42e578f29513 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -445,6 +445,8 @@ Deprecations - :func:`SeriesGroupBy.nth` has deprecated ``True`` in favor of ``'all'`` for its kwarg ``dropna`` (:issue:`11038`). +.. _whatsnew_0210.deprecations.argmin_min + Series.argmax and Series.argmin ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -452,21 +454,17 @@ Series.argmax and Series.argmin - The behavior of :func:`Series.argmin` has been deprecated in favor of :func:`Series.idxmin` (:issue:`16830`) For compatibility with NumPy arrays, ``pd.Series`` implements ``argmax`` and -``argmin``. Since pandas 0.13 :func:`Series.argmax` and -:func:`Series.argmin` returned the *label* of the maximum and minimum, +``argmin``. Since pandas 0.13.0, ``argmax`` has been an alias for +:meth:`pandas.Series.idxmax`, and ``argmin`` has been an alias for +:meth:`pandas.Series.idxmin`. They return the *label* of the maximum or minimum, rather than the *position*. -Since returning the positional ``argmax`` and ``argmin`` can be useful, -we've deprecated the current behavior of :func:`Series.argmax` and -:func:`Series.argmin`. Using either of these will emit a ``FutureWarning``. - -If you were using ``Series.argmin`` and ``Series.argmax``, please switch to using -``idxmin`` and ``idxmax``. In the future, ``Series.argmin`` will return the -*position* of the minimum. Likewise for ``Series.argmax``. - -Until this functionality is implemented in the future, we recommend using -``Series.values.argmin()`` and ``Series.values.argmax()`` for returning -the positional ``argmin`` and ``argmax``. +We've deprecated the current behavior of ``Series.argmax`` and +``Series.argmin``. Using either of these will emit a ``FutureWarning``. Use +:meth:`Series.idxmax` if you want the label of the maximum. Use +``Series.values.argmax()`` if you want the position of the maximum. Likewise for +the minimum. In a future release ``Series.argmax`` and ``Series.argmin`` will +return the position of the maximum or minimum. .. _whatsnew_0210.prior_deprecations: From db08dda87f6c6d44e1cfb5276ccb9e4c05e0e6ba Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Sun, 24 Sep 2017 08:41:44 -0500 Subject: [PATCH 05/12] Change sparse series test --- pandas/tests/sparse/test_series.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/tests/sparse/test_series.py b/pandas/tests/sparse/test_series.py index b247c595da0fe..451f369593347 100644 --- a/pandas/tests/sparse/test_series.py +++ b/pandas/tests/sparse/test_series.py @@ -1,7 +1,6 @@ # pylint: disable-msg=E1101,W0612 import operator -import warnings from datetime import datetime import pytest @@ -1391,11 +1390,12 @@ def test_deprecated_numpy_func_call(self): funcs = ['argmin', 'argmax'] for func in funcs: for series in ('bseries', 'zbseries'): - with warnings.catch_warnings(): - warnings.simplefilter("ignore") + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): getattr(np, func)(getattr(self, series)) - with tm.assert_produces_warning(FutureWarning): + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): getattr(getattr(self, series), func)() From 080fb06b84bd55aa3e8e39b6e701341ff5912319 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Sun, 24 Sep 2017 10:33:23 -0500 Subject: [PATCH 06/12] Skip on py2 --- pandas/tests/series/test_analytics.py | 4 +++- pandas/tests/sparse/test_series.py | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pandas/tests/series/test_analytics.py b/pandas/tests/series/test_analytics.py index de680a6f0593f..46686685864bf 100644 --- a/pandas/tests/series/test_analytics.py +++ b/pandas/tests/series/test_analytics.py @@ -19,7 +19,7 @@ import pandas.core.nanops as nanops -from pandas.compat import lrange, range, is_platform_windows +from pandas.compat import lrange, range, is_platform_windows, PY2 from pandas import compat from pandas.util.testing import (assert_series_equal, assert_almost_equal, assert_frame_equal, assert_index_equal) @@ -1242,6 +1242,7 @@ def test_idxmin(self): result = s.idxmin() assert result == 1 + @pytest.mark.skipif(PY2, reason="Buggy assertion on warning") def test_numpy_argmin_deprecated(self): # See gh-16830 data = np.arange(10) @@ -1313,6 +1314,7 @@ def test_idxmax(self): result = s.idxmin() assert result == 1.1 + @pytest.mark.skipif(PY2, reason="Buggy assertion on warning") def test_numpy_argmax_deprecated(self): # See gh-16830 data = np.random.randint(0, 11, size=10) diff --git a/pandas/tests/sparse/test_series.py b/pandas/tests/sparse/test_series.py index 451f369593347..8921593583d97 100644 --- a/pandas/tests/sparse/test_series.py +++ b/pandas/tests/sparse/test_series.py @@ -12,7 +12,7 @@ from pandas import Series, DataFrame, bdate_range, isna, compat from pandas.tseries.offsets import BDay import pandas.util.testing as tm -from pandas.compat import range +from pandas.compat import range, PY2 from pandas.core.reshape.util import cartesian_product import pandas.core.sparse.frame as spf @@ -1384,6 +1384,7 @@ def test_numpy_func_call(self): for series in ('bseries', 'zbseries'): getattr(np, func)(getattr(self, series)) + @pytest.mark.skipif(PY2, reason="Buggy assertion on warning") def test_deprecated_numpy_func_call(self): # NOTE: These should be add to the 'test_numpy_func_call' test above # once the behavior of argmin/argmax is corrected. From e979c601b015092c43f4f4ef4eb18679277b7edc Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 25 Sep 2017 14:56:17 -0500 Subject: [PATCH 07/12] Change to idxmin --- pandas/tests/series/test_operators.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/pandas/tests/series/test_operators.py b/pandas/tests/series/test_operators.py index 114a055de8195..7defaefc63f8d 100644 --- a/pandas/tests/series/test_operators.py +++ b/pandas/tests/series/test_operators.py @@ -1872,33 +1872,33 @@ def test_op_duplicate_index(self): ), ] ) - def test_assert_argminmax_raises(self, test_input, error_type): + def test_assert_idxminmax_raises(self, test_input, error_type): """ Cases where ``Series.argmax`` and related should raise an exception """ with pytest.raises(error_type): - test_input.argmin() + test_input.idxmin() with pytest.raises(error_type): - test_input.argmin(skipna=False) + test_input.idxmin(skipna=False) with pytest.raises(error_type): - test_input.argmax() + test_input.idxmax() with pytest.raises(error_type): - test_input.argmax(skipna=False) + test_input.idxmax(skipna=False) - def test_argminmax_with_inf(self): + def test_idxminmax_with_inf(self): # For numeric data with NA and Inf (GH #13595) s = pd.Series([0, -np.inf, np.inf, np.nan]) - assert s.argmin() == 1 - assert np.isnan(s.argmin(skipna=False)) + assert s.idxmin() == 1 + assert np.isnan(s.idxmin(skipna=False)) assert s.argmax() == 2 - assert np.isnan(s.argmax(skipna=False)) + assert np.isnan(s.idxmax(skipna=False)) # Using old-style behavior that treats floating point nan, -inf, and # +inf as missing with pd.option_context('mode.use_inf_as_na', True): - assert s.argmin() == 0 - assert np.isnan(s.argmin(skipna=False)) + assert s.idxmin() == 0 + assert np.isnan(s.idxmin(skipna=False)) assert s.argmax() == 0 np.isnan(s.argmax(skipna=False)) From b2501b2c2987b7e705559719171d98082a729447 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 25 Sep 2017 15:18:06 -0500 Subject: [PATCH 08/12] Remove py2 skips --- pandas/tests/series/test_analytics.py | 4 +--- pandas/tests/sparse/test_series.py | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pandas/tests/series/test_analytics.py b/pandas/tests/series/test_analytics.py index 8750e33cb2d8a..deb990d491dad 100644 --- a/pandas/tests/series/test_analytics.py +++ b/pandas/tests/series/test_analytics.py @@ -19,7 +19,7 @@ import pandas.core.nanops as nanops -from pandas.compat import lrange, range, is_platform_windows, PY2 +from pandas.compat import lrange, range, is_platform_windows from pandas import compat from pandas.util.testing import (assert_series_equal, assert_almost_equal, assert_frame_equal, assert_index_equal) @@ -1242,7 +1242,6 @@ def test_idxmin(self): result = s.idxmin() assert result == 1 - @pytest.mark.skipif(PY2, reason="Buggy assertion on warning") def test_numpy_argmin_deprecated(self): # See gh-16830 data = np.arange(10) @@ -1314,7 +1313,6 @@ def test_idxmax(self): result = s.idxmin() assert result == 1.1 - @pytest.mark.skipif(PY2, reason="Buggy assertion on warning") def test_numpy_argmax_deprecated(self): # See gh-16830 data = np.random.randint(0, 11, size=10) diff --git a/pandas/tests/sparse/test_series.py b/pandas/tests/sparse/test_series.py index 8921593583d97..451f369593347 100644 --- a/pandas/tests/sparse/test_series.py +++ b/pandas/tests/sparse/test_series.py @@ -12,7 +12,7 @@ from pandas import Series, DataFrame, bdate_range, isna, compat from pandas.tseries.offsets import BDay import pandas.util.testing as tm -from pandas.compat import range, PY2 +from pandas.compat import range from pandas.core.reshape.util import cartesian_product import pandas.core.sparse.frame as spf @@ -1384,7 +1384,6 @@ def test_numpy_func_call(self): for series in ('bseries', 'zbseries'): getattr(np, func)(getattr(self, series)) - @pytest.mark.skipif(PY2, reason="Buggy assertion on warning") def test_deprecated_numpy_func_call(self): # NOTE: These should be add to the 'test_numpy_func_call' test above # once the behavior of argmin/argmax is corrected. From 7ebf9cd01d0d84769edb33a0847530d4e6c4bb7b Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 25 Sep 2017 16:39:22 -0500 Subject: [PATCH 09/12] Catch more warnings --- pandas/io/formats/format.py | 2 +- pandas/tests/series/test_operators.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 547b9676717c9..c7a36af3a70f8 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -599,7 +599,7 @@ def to_string(self): else: # max_cols == 0. Try to fit frame to terminal text = self.adj.adjoin(1, *strcols).split('\n') row_lens = Series(text).apply(len) - max_len_col_ix = np.argmax(row_lens) + max_len_col_ix = row_lens.idxmax() max_len = row_lens[max_len_col_ix] headers = [ele[0] for ele in strcols] # Size of last col determines dot col size. See diff --git a/pandas/tests/series/test_operators.py b/pandas/tests/series/test_operators.py index 7defaefc63f8d..a7ce7ec1ea04f 100644 --- a/pandas/tests/series/test_operators.py +++ b/pandas/tests/series/test_operators.py @@ -1892,7 +1892,7 @@ def test_idxminmax_with_inf(self): assert s.idxmin() == 1 assert np.isnan(s.idxmin(skipna=False)) - assert s.argmax() == 2 + assert s.idxmax() == 2 assert np.isnan(s.idxmax(skipna=False)) # Using old-style behavior that treats floating point nan, -inf, and @@ -1900,5 +1900,5 @@ def test_idxminmax_with_inf(self): with pd.option_context('mode.use_inf_as_na', True): assert s.idxmin() == 0 assert np.isnan(s.idxmin(skipna=False)) - assert s.argmax() == 0 + assert s.idxmax() == 0 np.isnan(s.argmax(skipna=False)) From 128f8d40804d6e37bd5dfd97d8c06d294f110426 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Tue, 26 Sep 2017 07:52:22 -0500 Subject: [PATCH 10/12] Final switch to idxmax --- pandas/tests/series/test_operators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/series/test_operators.py b/pandas/tests/series/test_operators.py index a7ce7ec1ea04f..c8cc80b1cf4b1 100644 --- a/pandas/tests/series/test_operators.py +++ b/pandas/tests/series/test_operators.py @@ -1901,4 +1901,4 @@ def test_idxminmax_with_inf(self): assert s.idxmin() == 0 assert np.isnan(s.idxmin(skipna=False)) assert s.idxmax() == 0 - np.isnan(s.argmax(skipna=False)) + np.isnan(s.idxmax(skipna=False)) From e106a186709887674155dd5a2d4ae46c127769b7 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Tue, 26 Sep 2017 09:04:07 -0500 Subject: [PATCH 11/12] Consistent tests, refactor to_string --- pandas/io/formats/format.py | 4 +--- pandas/tests/series/test_analytics.py | 15 ++++++--------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index c7a36af3a70f8..386d9c3ffe30d 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -598,9 +598,7 @@ def to_string(self): text = self._join_multiline(*strcols) else: # max_cols == 0. Try to fit frame to terminal text = self.adj.adjoin(1, *strcols).split('\n') - row_lens = Series(text).apply(len) - max_len_col_ix = row_lens.idxmax() - max_len = row_lens[max_len_col_ix] + max_len = Series(text).str.len().max() headers = [ele[0] for ele in strcols] # Size of last col determines dot col size. See # `self._to_str_columns diff --git a/pandas/tests/series/test_analytics.py b/pandas/tests/series/test_analytics.py index deb990d491dad..da1b83880dfd7 100644 --- a/pandas/tests/series/test_analytics.py +++ b/pandas/tests/series/test_analytics.py @@ -1244,7 +1244,7 @@ def test_idxmin(self): def test_numpy_argmin_deprecated(self): # See gh-16830 - data = np.arange(10) + data = np.arange(1, 11) s = Series(data) with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): @@ -1253,14 +1253,13 @@ def test_numpy_argmin_deprecated(self): # until the implemention of Series.argmin is corrected. result = np.argmin(s) - assert result == 0 + assert result == 1 with tm.assert_produces_warning(FutureWarning): # argmin is aliased to idxmin result = s.argmin() - expected = s.idxmin() - assert result == expected + assert result == 1 if not _np_version_under1p10: with tm.assert_produces_warning(FutureWarning, @@ -1315,8 +1314,7 @@ def test_idxmax(self): def test_numpy_argmax_deprecated(self): # See gh-16830 - data = np.random.randint(0, 11, size=10) - data = np.arange(10) + data = np.arange(1, 11) s = Series(data) with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): @@ -1324,14 +1322,13 @@ def test_numpy_argmax_deprecated(self): # warning when calling np.argmax. This behavior is temporary # until the implemention of Series.argmax is corrected. result = np.argmax(s) - assert result == 9 + assert result == 10 with tm.assert_produces_warning(FutureWarning): # argmax is aliased to idxmax result = s.argmax() - expected = s.idxmax() - assert result == expected + assert result == 10 if not _np_version_under1p10: with tm.assert_produces_warning(FutureWarning, From 426d8ebccbcd7950c4ad9d85ccd457d1ad1ad02b Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Tue, 26 Sep 2017 09:24:39 -0500 Subject: [PATCH 12/12] Fixed tests --- pandas/tests/series/test_analytics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/series/test_analytics.py b/pandas/tests/series/test_analytics.py index da1b83880dfd7..9f5e4f2ac4b6e 100644 --- a/pandas/tests/series/test_analytics.py +++ b/pandas/tests/series/test_analytics.py @@ -1246,7 +1246,7 @@ def test_numpy_argmin_deprecated(self): # See gh-16830 data = np.arange(1, 11) - s = Series(data) + s = Series(data, index=data) with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): # The deprecation of Series.argmin also causes a deprecation # warning when calling np.argmin. This behavior is temporary @@ -1316,7 +1316,7 @@ def test_numpy_argmax_deprecated(self): # See gh-16830 data = np.arange(1, 11) - s = Series(data) + s = Series(data, index=data) with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): # The deprecation of Series.argmax also causes a deprecation # warning when calling np.argmax. This behavior is temporary