-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
API: harmonize drop/reindex/rename args (GH12392) - drop #17644
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
Changes from all commits
4293cc6
88ec872
6212b2a
ef82853
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2333,14 +2333,23 @@ def reindex_like(self, other, method=None, copy=True, limit=None, | |
|
||
return self.reindex(**d) | ||
|
||
def drop(self, labels, axis=0, level=None, inplace=False, errors='raise'): | ||
def drop(self, labels=None, axis=0, index=None, columns=None, level=None, | ||
inplace=False, errors='raise'): | ||
""" | ||
Return new object with labels in requested axis removed. | ||
|
||
Parameters | ||
---------- | ||
labels : single label or list-like | ||
Index or column labels to drop. | ||
axis : int or axis name | ||
Whether to drop labels from the index (0 / 'index') or | ||
columns (1 / 'columns'). | ||
index, columns : single label or list-like | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps add a |
||
Alternative to specifying `axis` (``labels, axis=1`` is | ||
equivalent to ``columns=labels``). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add a versionadded tag |
||
|
||
.. versionadded:: 0.21.0 | ||
level : int or level name, default None | ||
For MultiIndex | ||
inplace : bool, default False | ||
|
@@ -2354,36 +2363,80 @@ def drop(self, labels, axis=0, level=None, inplace=False, errors='raise'): | |
|
||
Examples | ||
-------- | ||
>>> df = pd.DataFrame([[1, 2, 3, 4], | ||
... [5, 6, 7, 8], | ||
... [9, 1, 2, 3], | ||
... [4, 5, 6, 7] | ||
... ], | ||
... columns=list('ABCD')) | ||
>>> df = pd.DataFrame(np.arange(12).reshape(3,4), | ||
columns=['A', 'B', 'C', 'D']) | ||
>>> df | ||
A B C D | ||
0 1 2 3 4 | ||
1 5 6 7 8 | ||
2 9 1 2 3 | ||
3 4 5 6 7 | ||
A B C D | ||
0 0 1 2 3 | ||
1 4 5 6 7 | ||
2 8 9 10 11 | ||
|
||
Drop columns | ||
|
||
>>> df.drop(['B', 'C'], axis=1) | ||
A D | ||
0 0 3 | ||
1 4 7 | ||
2 8 11 | ||
|
||
>>> df.drop(columns=['B', 'C']) | ||
A D | ||
0 0 3 | ||
1 4 7 | ||
2 8 11 | ||
|
||
Drop a row by index | ||
|
||
>>> df.drop([0, 1]) | ||
A B C D | ||
2 9 1 2 3 | ||
3 4 5 6 7 | ||
A B C D | ||
2 8 9 10 11 | ||
|
||
Drop columns | ||
Notes | ||
----- | ||
Specifying both `labels` and `index` or `columns` will raise a | ||
ValueError. | ||
|
||
>>> df.drop(['A', 'B'], axis=1) | ||
C D | ||
0 3 4 | ||
1 7 8 | ||
2 2 3 | ||
3 6 7 | ||
""" | ||
inplace = validate_bool_kwarg(inplace, 'inplace') | ||
|
||
if labels is not None: | ||
if index is not None or columns is not None: | ||
raise ValueError("Cannot specify both 'labels' and " | ||
"'index'/'columns'") | ||
axis_name = self._get_axis_name(axis) | ||
axes = {axis_name: labels} | ||
elif index is not None or columns is not None: | ||
axes, _ = self._construct_axes_from_arguments((index, columns), {}) | ||
else: | ||
raise ValueError("Need to specify at least one of 'labels', " | ||
"'index' or 'columns'") | ||
|
||
obj = self | ||
|
||
for axis, labels in axes.items(): | ||
if labels is not None: | ||
obj = obj._drop_axis(labels, axis, level=level, errors=errors) | ||
|
||
if inplace: | ||
self._update_inplace(obj) | ||
else: | ||
return obj | ||
|
||
def _drop_axis(self, labels, axis, level=None, errors='raise'): | ||
""" | ||
Drop labels from specified axis. Used in the ``drop`` method | ||
internally. | ||
|
||
Parameters | ||
---------- | ||
labels : single label or list-like | ||
axis : int or axis name | ||
level : int or level name, default None | ||
For MultiIndex | ||
errors : {'ignore', 'raise'}, default 'raise' | ||
If 'ignore', suppress error and existing labels are dropped. | ||
|
||
""" | ||
axis = self._get_axis_number(axis) | ||
axis_name = self._get_axis_name(axis) | ||
axis, axis_ = self._get_axis(axis), axis | ||
|
@@ -2416,10 +2469,7 @@ def drop(self, labels, axis=0, level=None, inplace=False, errors='raise'): | |
|
||
result = self.loc[tuple(slicer)] | ||
|
||
if inplace: | ||
self._update_inplace(result) | ||
else: | ||
return result | ||
return result | ||
|
||
def _update_inplace(self, result, verify_is_copy=True): | ||
""" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -146,6 +146,41 @@ def test_drop_multiindex_not_lexsorted(self): | |
|
||
tm.assert_frame_equal(result, expected) | ||
|
||
def test_drop_api_equivalence(self): | ||
# equivalence of the labels/axis and index/columns API's (GH12392) | ||
df = DataFrame([[1, 2, 3], [3, 4, 5], [5, 6, 7]], | ||
index=['a', 'b', 'c'], | ||
columns=['d', 'e', 'f']) | ||
|
||
res1 = df.drop('a') | ||
res2 = df.drop(index='a') | ||
tm.assert_frame_equal(res1, res2) | ||
|
||
res1 = df.drop('d', 1) | ||
res2 = df.drop(columns='d') | ||
tm.assert_frame_equal(res1, res2) | ||
|
||
res1 = df.drop(labels='e', axis=1) | ||
res2 = df.drop(columns='e') | ||
tm.assert_frame_equal(res1, res2) | ||
|
||
res1 = df.drop(['a'], axis=0) | ||
res2 = df.drop(index=['a']) | ||
tm.assert_frame_equal(res1, res2) | ||
|
||
res1 = df.drop(['a'], axis=0).drop(['d'], axis=1) | ||
res2 = df.drop(index=['a'], columns=['d']) | ||
tm.assert_frame_equal(res1, res2) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. test with columns as well There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you mean for the error test? (added one for that) Or for one of the tests above? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep |
||
with pytest.raises(ValueError): | ||
df.drop(labels='a', index='b') | ||
|
||
with pytest.raises(ValueError): | ||
df.drop(labels='a', columns='b') | ||
|
||
with pytest.raises(ValueError): | ||
df.drop(axis=1) | ||
|
||
def test_merge_join_different_levels(self): | ||
# GH 9455 | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add ref here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is only needed when you actually want to explicitly link to it from somewhere else in the docs, so I personally prefer to only add it when actually needed
(bug can certainly add it for consistency)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, all sub-sections should have a reference as a general rule. yes we may not always link to it, but by definition when creating a non-trivial sub-section it should have a reference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is nothing "by definition" about it (I mean, sphinx does not require it). IMO it just gives more overhead by always asking contributors to do this.