From d0b39ea165589f3629381abe0edd38c5e6515136 Mon Sep 17 00:00:00 2001 From: aschade Date: Sat, 13 Jan 2018 14:55:41 -0500 Subject: [PATCH 01/12] DOC: Updated doc --- doc/source/whatsnew/v0.23.0.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index 3a3c2bf0c5ae4..bb1e00bda53e2 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -453,6 +453,7 @@ Reshaping - Bug in :func:`Dataframe.pivot_table` which fails when the ``aggfunc`` arg is of type string. The behavior is now consistent with other methods like ``agg`` and ``apply`` (:issue:`18713`) - Bug in :func:`DataFrame.merge` in which merging using ``Index`` objects as vectors raised an Exception (:issue:`19038`) - Bug in :func:`DataFrame.stack`, :func:`DataFrame.unstack`, :func:`Series.unstack` which were not returning subclasses (:issue:`15563`) +- Bug in :func:`DataFrame.drop`, `ValueError` now raises when dropping an `Index` that has duplicates - Numeric From f43dbf83e878c9d7716ee154c0ab2719c1ffbe51 Mon Sep 17 00:00:00 2001 From: aschade Date: Sat, 13 Jan 2018 14:56:46 -0500 Subject: [PATCH 02/12] TST: Added test for dropping index with dup cols --- pandas/tests/frame/test_mutate_columns.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pandas/tests/frame/test_mutate_columns.py b/pandas/tests/frame/test_mutate_columns.py index 9acdf2f17d86a..c0706430616e5 100644 --- a/pandas/tests/frame/test_mutate_columns.py +++ b/pandas/tests/frame/test_mutate_columns.py @@ -257,3 +257,21 @@ def test_insert_column_bug_4032(self): expected = DataFrame([[1.3, 1, 1.1], [2.3, 2, 2.2]], columns=['c', 'a', 'b']) assert_frame_equal(result, expected) + + data = [[1, 2, 3], [1, 2, 3]] + + @pytest.mark.parametrize('actual', [ + DataFrame(data=data, index=['a', 'a']), + DataFrame(data=data, index=['a', 'b']), + DataFrame(data=data, index=['a', 'b']).set_index([0, 1]), + DataFrame(data=data, index=['a', 'a']).set_index([0, 1]) + ]) + def test_raise_on_drop_duplicate_index(self, actual): + + # issue 19186 + level = 0 if isinstance(actual.index, MultiIndex) else None + with pytest.raises(ValueError): + actual.drop('c', level=level, axis=0) + expected_no_err = actual.drop('c', axis=0, level=level, + errors='ignore') + assert_frame_equal(expected_no_err, actual) From a4618bfe46405bbab3f20c120171c5e3386b7ec9 Mon Sep 17 00:00:00 2001 From: aschade Date: Sat, 13 Jan 2018 14:57:07 -0500 Subject: [PATCH 03/12] BUG: Raise on drop on dup index --- pandas/core/generic.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index cef1e551f948e..b3e00549ccca0 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2909,6 +2909,9 @@ def _drop_axis(self, labels, axis, level=None, errors='raise'): else: indexer = ~axis.isin(labels) + if all(indexer) and errors == 'raise': + raise ValueError('{} not found in axis'.format(labels)) + slicer = [slice(None)] * self.ndim slicer[self._get_axis_number(axis_name)] = indexer From b49f78d2f733d541b9182d70f2998567b2b683c2 Mon Sep 17 00:00:00 2001 From: aschade Date: Sat, 13 Jan 2018 15:46:27 -0500 Subject: [PATCH 04/12] DOC: Fixed docs --- doc/source/whatsnew/v0.23.0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index bb1e00bda53e2..dfbfcc7016219 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -453,7 +453,7 @@ Reshaping - Bug in :func:`Dataframe.pivot_table` which fails when the ``aggfunc`` arg is of type string. The behavior is now consistent with other methods like ``agg`` and ``apply`` (:issue:`18713`) - Bug in :func:`DataFrame.merge` in which merging using ``Index`` objects as vectors raised an Exception (:issue:`19038`) - Bug in :func:`DataFrame.stack`, :func:`DataFrame.unstack`, :func:`Series.unstack` which were not returning subclasses (:issue:`15563`) -- Bug in :func:`DataFrame.drop`, `ValueError` now raises when dropping an `Index` that has duplicates +- Bug in :func:`DataFrame.drop`, ``ValueError`` now raises when dropping an ``Index`` that has duplicates (:issue:`19186`) - Numeric From 43fe5b06b2245f99425c7a1d6512293436447b6f Mon Sep 17 00:00:00 2001 From: aschade Date: Sat, 13 Jan 2018 16:12:05 -0500 Subject: [PATCH 05/12] Use numpy all --- pandas/core/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index b3e00549ccca0..27ce8b4c84440 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2909,7 +2909,7 @@ def _drop_axis(self, labels, axis, level=None, errors='raise'): else: indexer = ~axis.isin(labels) - if all(indexer) and errors == 'raise': + if errors == 'raise' and indexer.all(): raise ValueError('{} not found in axis'.format(labels)) slicer = [slice(None)] * self.ndim From 7ceafa10e1da13e431522c379c755c3a84aed0dc Mon Sep 17 00:00:00 2001 From: aschade Date: Sun, 14 Jan 2018 14:43:40 -0500 Subject: [PATCH 06/12] TST: Updated tests to account for KeyError now being raised --- .../tests/frame/test_axis_select_reindex.py | 34 +++++++++++++++---- pandas/tests/frame/test_mutate_columns.py | 18 ---------- pandas/tests/indexes/test_base.py | 8 ++--- pandas/tests/series/test_indexing.py | 6 ++-- pandas/tests/test_panel.py | 2 +- 5 files changed, 36 insertions(+), 32 deletions(-) diff --git a/pandas/tests/frame/test_axis_select_reindex.py b/pandas/tests/frame/test_axis_select_reindex.py index 343e235fb741c..a0a3578d96325 100644 --- a/pandas/tests/frame/test_axis_select_reindex.py +++ b/pandas/tests/frame/test_axis_select_reindex.py @@ -41,8 +41,8 @@ def test_drop_names(self): assert obj.columns.name == 'second' assert list(df.columns) == ['d', 'e', 'f'] - pytest.raises(ValueError, df.drop, ['g']) - pytest.raises(ValueError, df.drop, ['g'], 1) + pytest.raises(KeyError, df.drop, ['g']) + pytest.raises(KeyError, df.drop, ['g'], 1) # errors = 'ignore' dropped = df.drop(['g'], errors='ignore') @@ -87,10 +87,10 @@ def test_drop(self): assert_frame_equal(simple.drop( [0, 3], axis='index'), simple.loc[[1, 2], :]) - pytest.raises(ValueError, simple.drop, 5) - pytest.raises(ValueError, simple.drop, 'C', 1) - pytest.raises(ValueError, simple.drop, [1, 5]) - pytest.raises(ValueError, simple.drop, ['A', 'C'], 1) + pytest.raises(KeyError, simple.drop, 5) + pytest.raises(KeyError, simple.drop, 'C', 1) + pytest.raises(KeyError, simple.drop, [1, 5]) + pytest.raises(KeyError, simple.drop, ['A', 'C'], 1) # errors = 'ignore' assert_frame_equal(simple.drop(5, errors='ignore'), simple) @@ -1128,3 +1128,25 @@ def test_reindex_multi(self): expected = df.reindex([0, 1]).reindex(columns=['a', 'b']) assert_frame_equal(result, expected) + + data = [[1, 2, 3], [1, 2, 3]] + + @pytest.mark.parametrize('actual', [ + DataFrame(data=data, index=['a', 'a']), + DataFrame(data=data, index=['a', 'b']), + DataFrame(data=data, index=['a', 'b']).set_index([0, 1]), + DataFrame(data=data, index=['a', 'a']).set_index([0, 1]) + ]) + def test_raise_on_drop_duplicate_index(self, actual): + + # issue 19186 + level = 0 if isinstance(actual.index, MultiIndex) else None + with pytest.raises(KeyError): + actual.drop('c', level=level, axis=0) + actual.T.drop('c', level=level, axis=1) + expected_no_err = actual.drop('c', axis=0, level=level, + errors='ignore') + assert_frame_equal(expected_no_err, actual) + expected_no_err = actual.T.drop('c', axis=1, level=level, + errors='ignore') + assert_frame_equal(expected_no_err.T, actual) diff --git a/pandas/tests/frame/test_mutate_columns.py b/pandas/tests/frame/test_mutate_columns.py index c0706430616e5..9acdf2f17d86a 100644 --- a/pandas/tests/frame/test_mutate_columns.py +++ b/pandas/tests/frame/test_mutate_columns.py @@ -257,21 +257,3 @@ def test_insert_column_bug_4032(self): expected = DataFrame([[1.3, 1, 1.1], [2.3, 2, 2.2]], columns=['c', 'a', 'b']) assert_frame_equal(result, expected) - - data = [[1, 2, 3], [1, 2, 3]] - - @pytest.mark.parametrize('actual', [ - DataFrame(data=data, index=['a', 'a']), - DataFrame(data=data, index=['a', 'b']), - DataFrame(data=data, index=['a', 'b']).set_index([0, 1]), - DataFrame(data=data, index=['a', 'a']).set_index([0, 1]) - ]) - def test_raise_on_drop_duplicate_index(self, actual): - - # issue 19186 - level = 0 if isinstance(actual.index, MultiIndex) else None - with pytest.raises(ValueError): - actual.drop('c', level=level, axis=0) - expected_no_err = actual.drop('c', axis=0, level=level, - errors='ignore') - assert_frame_equal(expected_no_err, actual) diff --git a/pandas/tests/indexes/test_base.py b/pandas/tests/indexes/test_base.py index c4e8682934369..508c3a73f48c7 100644 --- a/pandas/tests/indexes/test_base.py +++ b/pandas/tests/indexes/test_base.py @@ -1396,8 +1396,8 @@ def test_drop(self): expected = self.strIndex[lrange(5) + lrange(10, n)] tm.assert_index_equal(dropped, expected) - pytest.raises(ValueError, self.strIndex.drop, ['foo', 'bar']) - pytest.raises(ValueError, self.strIndex.drop, ['1', 'bar']) + pytest.raises(KeyError, self.strIndex.drop, ['foo', 'bar']) + pytest.raises(KeyError, self.strIndex.drop, ['1', 'bar']) # errors='ignore' mixed = drop.tolist() + ['foo'] @@ -1419,7 +1419,7 @@ def test_drop(self): tm.assert_index_equal(dropped, expected) # errors='ignore' - pytest.raises(ValueError, ser.drop, [3, 4]) + pytest.raises(KeyError, ser.drop, [3, 4]) dropped = ser.drop(4, errors='ignore') expected = Index([1, 2, 3]) @@ -1448,7 +1448,7 @@ def test_drop_tuple(self, values, to_drop): removed = index.drop(to_drop[1]) for drop_me in to_drop[1], [to_drop[1]]: - pytest.raises(ValueError, removed.drop, drop_me) + pytest.raises(KeyError, removed.drop, drop_me) def test_tuple_union_bug(self): import pandas diff --git a/pandas/tests/series/test_indexing.py b/pandas/tests/series/test_indexing.py index 29b4363ec70b9..bafc6d268c266 100644 --- a/pandas/tests/series/test_indexing.py +++ b/pandas/tests/series/test_indexing.py @@ -1838,8 +1838,8 @@ def test_drop(self): # single string/tuple-like s = Series(range(3), index=list('abc')) - pytest.raises(ValueError, s.drop, 'bc') - pytest.raises(ValueError, s.drop, ('a', )) + pytest.raises(KeyError, s.drop, 'bc') + pytest.raises(KeyError, s.drop, ('a', )) # errors='ignore' s = Series(range(3), index=list('abc')) @@ -1861,7 +1861,7 @@ def test_drop(self): # GH 16877 s = Series([2, 3], index=[0, 1]) - with tm.assert_raises_regex(ValueError, 'not contained in axis'): + with tm.assert_raises_regex(KeyError, 'not contained in axis'): s.drop([False, True]) def test_align(self): diff --git a/pandas/tests/test_panel.py b/pandas/tests/test_panel.py index 770560134d8d6..1955fc301be9b 100644 --- a/pandas/tests/test_panel.py +++ b/pandas/tests/test_panel.py @@ -2302,7 +2302,7 @@ def check_drop(drop_val, axis_number, aliases, expected): expected = Panel({"One": df}) check_drop('Two', 0, ['items'], expected) - pytest.raises(ValueError, panel.drop, 'Three') + pytest.raises(KeyError, panel.drop, 'Three') # errors = 'ignore' dropped = panel.drop('Three', errors='ignore') From 5f7e6a2f776063770b47559381650b94c976f243 Mon Sep 17 00:00:00 2001 From: aschade Date: Sun, 14 Jan 2018 14:44:04 -0500 Subject: [PATCH 07/12] DOC: Moved string to diff location --- doc/source/whatsnew/v0.23.0.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index dfbfcc7016219..36aea533b9160 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -408,6 +408,8 @@ Indexing - Bug in :func:`MultiIndex.set_labels` which would cause casting (and potentially clipping) of the new labels if the ``level`` argument is not 0 or a list like [0, 1, ... ] (:issue:`19057`) - Bug in ``str.extractall`` when there were no matches empty :class:`Index` was returned instead of appropriate :class:`MultiIndex` (:issue:`19034`) - Bug in :class:`IntervalIndex` where set operations that returned an empty ``IntervalIndex`` had the wrong dtype (:issue:`19101`) +- Bug in :func:`DataFrame.drop`, ``ValueError`` now raises when dropping an ``Index`` that has duplicates (:issue:`19186`) +- I/O ^^^ @@ -453,7 +455,6 @@ Reshaping - Bug in :func:`Dataframe.pivot_table` which fails when the ``aggfunc`` arg is of type string. The behavior is now consistent with other methods like ``agg`` and ``apply`` (:issue:`18713`) - Bug in :func:`DataFrame.merge` in which merging using ``Index`` objects as vectors raised an Exception (:issue:`19038`) - Bug in :func:`DataFrame.stack`, :func:`DataFrame.unstack`, :func:`Series.unstack` which were not returning subclasses (:issue:`15563`) -- Bug in :func:`DataFrame.drop`, ``ValueError`` now raises when dropping an ``Index`` that has duplicates (:issue:`19186`) - Numeric From 6c7bcf258d1e138463fae19528c5299cc5b6242d Mon Sep 17 00:00:00 2001 From: aschade Date: Sun, 14 Jan 2018 14:50:54 -0500 Subject: [PATCH 08/12] BUG: Updated code to raise KeyError --- pandas/core/generic.py | 2 +- pandas/core/indexes/base.py | 4 ++-- pandas/core/reshape/pivot.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 27ce8b4c84440..bbbb18ddbbb50 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2910,7 +2910,7 @@ def _drop_axis(self, labels, axis, level=None, errors='raise'): indexer = ~axis.isin(labels) if errors == 'raise' and indexer.all(): - raise ValueError('{} not found in axis'.format(labels)) + raise KeyError('{} not found in axis'.format(labels)) slicer = [slice(None)] * self.ndim slicer[self._get_axis_number(axis_name)] = indexer diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index f634d809560ee..98488771f2341 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3767,8 +3767,8 @@ def drop(self, labels, errors='raise'): mask = indexer == -1 if mask.any(): if errors != 'ignore': - raise ValueError('labels %s not contained in axis' % - labels[mask]) + raise KeyError( + 'labels %s not contained in axis' % labels[mask]) indexer = indexer[~mask] return self.delete(indexer) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 77babf718d78c..0e92fc4edce85 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -75,7 +75,7 @@ def pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', for key in keys: try: values = values.drop(key) - except (TypeError, ValueError): + except (TypeError, ValueError, KeyError): pass values = list(values) From fa4c9fee5399d6c4edbb2445cd83ee1d6f03e78f Mon Sep 17 00:00:00 2001 From: aschade Date: Sun, 14 Jan 2018 15:01:59 -0500 Subject: [PATCH 09/12] DOC: Updated doc to include correct err being raised. --- doc/source/whatsnew/v0.23.0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index 36aea533b9160..c4896fe9514d1 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -408,7 +408,7 @@ Indexing - Bug in :func:`MultiIndex.set_labels` which would cause casting (and potentially clipping) of the new labels if the ``level`` argument is not 0 or a list like [0, 1, ... ] (:issue:`19057`) - Bug in ``str.extractall`` when there were no matches empty :class:`Index` was returned instead of appropriate :class:`MultiIndex` (:issue:`19034`) - Bug in :class:`IntervalIndex` where set operations that returned an empty ``IntervalIndex`` had the wrong dtype (:issue:`19101`) -- Bug in :func:`DataFrame.drop`, ``ValueError`` now raises when dropping an ``Index`` that has duplicates (:issue:`19186`) +- Bug in :func:`DataFrame.drop`, ``KeyError`` now raises when dropping an ``Index`` or column that has duplicates (:issue:`19186`) - I/O From adf2283baa6f7326e673f5e81cad8ccccf81804e Mon Sep 17 00:00:00 2001 From: aschade Date: Mon, 15 Jan 2018 13:43:18 -0500 Subject: [PATCH 10/12] DOC: Updated docstring and documentation --- doc/source/whatsnew/v0.23.0.txt | 3 ++- pandas/core/generic.py | 5 +++++ pandas/core/indexes/base.py | 5 +++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index c4896fe9514d1..97ec6effcb165 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -271,6 +271,7 @@ Other API Changes - :class:`IntervalIndex` and ``IntervalDtype`` no longer support categorical, object, and string subtypes (:issue:`19016`) - The default ``Timedelta`` constructor now accepts an ``ISO 8601 Duration`` string as an argument (:issue:`19040`) - ``IntervalDtype`` now returns ``True`` when compared against ``'interval'`` regardless of subtype, and ``IntervalDtype.name`` now returns ``'interval'`` regardless of subtype (:issue:`18980`) +- ``KeyError`` now raises instead of ``ValueError`` when using :meth:`drop()` to remove a non-existent element in an axis of ``Series``, ``Index``, ``DataFrame`` and ``Panel`` (:issue:`19186`) .. _whatsnew_0230.deprecations: @@ -408,7 +409,7 @@ Indexing - Bug in :func:`MultiIndex.set_labels` which would cause casting (and potentially clipping) of the new labels if the ``level`` argument is not 0 or a list like [0, 1, ... ] (:issue:`19057`) - Bug in ``str.extractall`` when there were no matches empty :class:`Index` was returned instead of appropriate :class:`MultiIndex` (:issue:`19034`) - Bug in :class:`IntervalIndex` where set operations that returned an empty ``IntervalIndex`` had the wrong dtype (:issue:`19101`) -- Bug in :func:`DataFrame.drop`, ``KeyError`` now raises when dropping an ``Index`` or column that has duplicates (:issue:`19186`) +- Bug in :func:`DataFrame.drop`, where no ``Exception`` is raised when dropping a non-existent element from an axis in ``Index`` (:issue:`19186`) - I/O diff --git a/pandas/core/generic.py b/pandas/core/generic.py index bbbb18ddbbb50..4ed53e36c47e5 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2806,6 +2806,11 @@ def drop(self, labels=None, axis=0, index=None, columns=None, level=None, ------- dropped : type of caller + Raises + ------ + KeyError + * If labels are not found in the selected axis + Examples -------- >>> df = pd.DataFrame(np.arange(12).reshape(3,4), diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 98488771f2341..d31cc363db038 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3760,6 +3760,11 @@ def drop(self, labels, errors='raise'): Returns ------- dropped : Index + + Raises + ------ + KeyError + * If labels are not found in the selected axis """ arr_dtype = 'object' if self.dtype == 'object' else None labels = _index_labels_to_array(labels, dtype=arr_dtype) From 556f95979fe82bf10140267a19fee74e576884cf Mon Sep 17 00:00:00 2001 From: Alexander Michael Schade <3345464+aschade@users.noreply.github.com> Date: Mon, 15 Jan 2018 13:52:32 -0500 Subject: [PATCH 11/12] Update v0.23.0.txt --- doc/source/whatsnew/v0.23.0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index 6f627b15dba40..e8e14bcc43a45 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -416,7 +416,7 @@ Indexing - Bug in :func:`MultiIndex.set_labels` which would cause casting (and potentially clipping) of the new labels if the ``level`` argument is not 0 or a list like [0, 1, ... ] (:issue:`19057`) - Bug in ``str.extractall`` when there were no matches empty :class:`Index` was returned instead of appropriate :class:`MultiIndex` (:issue:`19034`) - Bug in :class:`IntervalIndex` where set operations that returned an empty ``IntervalIndex`` had the wrong dtype (:issue:`19101`) -- Bug in :func:`DataFrame.drop`, where no ``Exception`` is raised when dropping a non-existent element from an axis in ``Index`` (:issue:`19186`) +- Bug in :func:`Index.drop()`, where no ``Exception`` is raised when dropping a non-existent element from an axis in ``Index`` (:issue:`19186`) - I/O From 5776bf3f3110fff0ae92fbab2710c4d22df769e3 Mon Sep 17 00:00:00 2001 From: aschade Date: Mon, 15 Jan 2018 21:11:55 -0500 Subject: [PATCH 12/12] DOC/TST: Updated docstring to show method correctly and updated test --- doc/source/whatsnew/v0.23.0.txt | 4 ++-- pandas/core/generic.py | 2 +- pandas/core/indexes/base.py | 2 +- pandas/tests/frame/test_axis_select_reindex.py | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index e8e14bcc43a45..450afa01a576e 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -272,7 +272,7 @@ Other API Changes - :class:`IntervalIndex` and ``IntervalDtype`` no longer support categorical, object, and string subtypes (:issue:`19016`) - The default ``Timedelta`` constructor now accepts an ``ISO 8601 Duration`` string as an argument (:issue:`19040`) - ``IntervalDtype`` now returns ``True`` when compared against ``'interval'`` regardless of subtype, and ``IntervalDtype.name`` now returns ``'interval'`` regardless of subtype (:issue:`18980`) -- ``KeyError`` now raises instead of ``ValueError`` when using :meth:`drop()` to remove a non-existent element in an axis of ``Series``, ``Index``, ``DataFrame`` and ``Panel`` (:issue:`19186`) +- ``KeyError`` now raises instead of ``ValueError`` in :meth:`~DataFrame.drop`, :meth:`~Panel.drop`, :meth:`~Series.drop`, :meth:`~Index.drop` when dropping a non-existent element in an axis with duplicates (:issue:`19186`) - :func:`Series.to_csv` now accepts a ``compression`` argument that works in the same way as the ``compression`` argument in :func:`DataFrame.to_csv` (:issue:`18958`) .. _whatsnew_0230.deprecations: @@ -416,7 +416,7 @@ Indexing - Bug in :func:`MultiIndex.set_labels` which would cause casting (and potentially clipping) of the new labels if the ``level`` argument is not 0 or a list like [0, 1, ... ] (:issue:`19057`) - Bug in ``str.extractall`` when there were no matches empty :class:`Index` was returned instead of appropriate :class:`MultiIndex` (:issue:`19034`) - Bug in :class:`IntervalIndex` where set operations that returned an empty ``IntervalIndex`` had the wrong dtype (:issue:`19101`) -- Bug in :func:`Index.drop()`, where no ``Exception`` is raised when dropping a non-existent element from an axis in ``Index`` (:issue:`19186`) +- Bug in :meth:`~DataFrame.drop`, :meth:`~Panel.drop`, :meth:`~Series.drop`, :meth:`~Index.drop` where no ``KeyError`` is raised when dropping a non-existent element from an axis that contains duplicates (:issue:`19186`) - I/O diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 4ed53e36c47e5..7ffef9c8a86d7 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2809,7 +2809,7 @@ def drop(self, labels=None, axis=0, index=None, columns=None, level=None, Raises ------ KeyError - * If labels are not found in the selected axis + If none of the labels are found in the selected axis Examples -------- diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index d31cc363db038..10c22884d7acf 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3764,7 +3764,7 @@ def drop(self, labels, errors='raise'): Raises ------ KeyError - * If labels are not found in the selected axis + If none of the labels are found in the selected axis """ arr_dtype = 'object' if self.dtype == 'object' else None labels = _index_labels_to_array(labels, dtype=arr_dtype) diff --git a/pandas/tests/frame/test_axis_select_reindex.py b/pandas/tests/frame/test_axis_select_reindex.py index a0a3578d96325..28e82f7585850 100644 --- a/pandas/tests/frame/test_axis_select_reindex.py +++ b/pandas/tests/frame/test_axis_select_reindex.py @@ -1143,6 +1143,7 @@ def test_raise_on_drop_duplicate_index(self, actual): level = 0 if isinstance(actual.index, MultiIndex) else None with pytest.raises(KeyError): actual.drop('c', level=level, axis=0) + with pytest.raises(KeyError): actual.T.drop('c', level=level, axis=1) expected_no_err = actual.drop('c', axis=0, level=level, errors='ignore')