-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
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
ENH: provide "inplace" argument to set_axis() #16994
Changes from all commits
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 |
---|---|---|
|
@@ -466,9 +466,91 @@ def _expand_axes(self, key): | |
|
||
return new_axes | ||
|
||
def set_axis(self, axis, labels): | ||
""" public verson of axis assignment """ | ||
setattr(self, self._get_axis_name(axis), labels) | ||
_shared_docs['set_axis'] = """Assign desired index to given axis | ||
|
||
Parameters | ||
---------- | ||
labels: list-like or Index | ||
The values for the new index | ||
axis : int or string, default 0 | ||
inplace : boolean, default None | ||
Whether to return a new %(klass)s instance. | ||
|
||
WARNING: inplace=None currently falls back to to True, but | ||
in a future version, will default to False. Use inplace=True | ||
explicitly rather than relying on the default. | ||
|
||
.. versionadded:: 0.21.0 | ||
The signature was uniformed to the rest of the API: previously, | ||
"axis" and "labels" were respectively the first and second | ||
positional arguments. | ||
|
||
Returns | ||
------- | ||
renamed : %(klass)s or None | ||
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. this needs updating 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. Not sure what you mean... anyway, I just made the following line more explicit |
||
An object of same type as caller if inplace=False, None otherwise. | ||
|
||
See Also | ||
-------- | ||
pandas.NDFrame.rename | ||
|
||
Examples | ||
-------- | ||
>>> s = pd.Series([1, 2, 3]) | ||
>>> s | ||
0 1 | ||
1 2 | ||
2 3 | ||
dtype: int64 | ||
>>> s.set_axis(['a', 'b', 'c'], axis=0, inplace=False) | ||
a 1 | ||
b 2 | ||
c 3 | ||
dtype: int64 | ||
>>> df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}) | ||
>>> df.set_axis(['a', 'b', 'c'], axis=0, inplace=False) | ||
A B | ||
a 1 4 | ||
b 2 5 | ||
c 3 6 | ||
>>> df.set_axis(['I', 'II'], axis=1, inplace=False) | ||
I II | ||
0 1 4 | ||
1 2 5 | ||
2 3 6 | ||
>>> df.set_axis(['i', 'ii'], axis=1, inplace=True) | ||
>>> df | ||
i ii | ||
0 1 4 | ||
1 2 5 | ||
2 3 6 | ||
|
||
""" | ||
|
||
@Appender(_shared_docs['set_axis'] % dict(klass='NDFrame')) | ||
def set_axis(self, labels, axis=0, inplace=None): | ||
if is_scalar(labels): | ||
warnings.warn( | ||
'set_axis now takes "labels" as first argument, and ' | ||
'"axis" as named parameter. The old form, with "axis" as ' | ||
'first parameter and \"labels\" as second, is still supported ' | ||
'but will be deprecated in a future version of pandas.', | ||
FutureWarning, stacklevel=2) | ||
labels, axis = axis, labels | ||
|
||
if inplace is None: | ||
warnings.warn( | ||
'set_axis currently defaults to operating inplace.\nThis ' | ||
'will change in a future version of pandas, use ' | ||
'inplace=True to avoid this warning.', | ||
FutureWarning, stacklevel=2) | ||
inplace = True | ||
if inplace: | ||
setattr(self, self._get_axis_name(axis), labels) | ||
else: | ||
obj = self.copy() | ||
obj.set_axis(labels, axis=axis, inplace=True) | ||
return obj | ||
|
||
def _set_axis(self, axis, labels): | ||
self._data.set_axis(axis, labels) | ||
|
@@ -875,7 +957,7 @@ def _set_axis_name(self, name, axis=0, inplace=False): | |
|
||
inplace = validate_bool_kwarg(inplace, 'inplace') | ||
renamed = self if inplace else self.copy() | ||
renamed.set_axis(axis, idx) | ||
renamed.set_axis(idx, axis=axis, inplace=True) | ||
if not inplace: | ||
return renamed | ||
|
||
|
@@ -5763,7 +5845,7 @@ def slice_shift(self, periods=1, axis=0): | |
|
||
new_obj = self._slice(vslicer, axis=axis) | ||
shifted_axis = self._get_axis(axis)[islicer] | ||
new_obj.set_axis(axis, shifted_axis) | ||
new_obj.set_axis(shifted_axis, axis=axis, inplace=True) | ||
|
||
return new_obj.__finalize__(self) | ||
|
||
|
@@ -5923,7 +6005,7 @@ def _tz_convert(ax, tz): | |
ax = _tz_convert(ax, tz) | ||
|
||
result = self._constructor(self._data, copy=copy) | ||
result.set_axis(axis, ax) | ||
result.set_axis(ax, axis=axis, inplace=True) | ||
return result.__finalize__(self) | ||
|
||
@deprecate_kwarg(old_arg_name='infer_dst', new_arg_name='ambiguous', | ||
|
@@ -5991,7 +6073,7 @@ def _tz_localize(ax, tz, ambiguous): | |
ax = _tz_localize(ax, tz, ambiguous) | ||
|
||
result = self._constructor(self._data, copy=copy) | ||
result.set_axis(axis, ax) | ||
result.set_axis(ax, axis=axis, inplace=True) | ||
return result.__finalize__(self) | ||
|
||
# ---------------------------------------------------------------------- | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -908,3 +908,62 @@ def test_set_reset_index(self): | |
df = df.set_index('B') | ||
|
||
df = df.reset_index() | ||
|
||
def test_set_axis_inplace(self): | ||
# GH14636 | ||
df = DataFrame({'A': [1.1, 2.2, 3.3], | ||
'B': [5.0, 6.1, 7.2], | ||
'C': [4.4, 5.5, 6.6]}, | ||
index=[2010, 2011, 2012]) | ||
|
||
expected = {0: df.copy(), | ||
1: df.copy()} | ||
expected[0].index = list('abc') | ||
expected[1].columns = list('abc') | ||
expected['index'] = expected[0] | ||
expected['columns'] = expected[1] | ||
|
||
for axis in expected: | ||
# inplace=True | ||
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. A sentence (on a newline) about why we issue |
||
# The FutureWarning comes from the fact that we would like to have | ||
# inplace default to False some day | ||
for inplace, warn in (None, FutureWarning), (True, None): | ||
kwargs = {'inplace': inplace} | ||
|
||
result = df.copy() | ||
with tm.assert_produces_warning(warn): | ||
result.set_axis(list('abc'), axis=axis, **kwargs) | ||
tm.assert_frame_equal(result, expected[axis]) | ||
|
||
# inplace=False | ||
result = df.set_axis(list('abc'), axis=axis, inplace=False) | ||
tm.assert_frame_equal(expected[axis], result) | ||
|
||
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. can you add a test for invalid axis (e.g. 'foo', or 2) 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 axis ='index' and axis='columns' (should work) 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.
(done: line 947) |
||
# omitting the "axis" parameter | ||
with tm.assert_produces_warning(None): | ||
result = df.set_axis(list('abc'), inplace=False) | ||
tm.assert_frame_equal(result, expected[0]) | ||
|
||
# wrong values for the "axis" parameter | ||
for axis in 3, 'foo': | ||
with tm.assert_raises_regex(ValueError, 'No axis named'): | ||
df.set_axis(list('abc'), axis=axis, inplace=False) | ||
|
||
def test_set_axis_old_signature(self): | ||
df = DataFrame({'A': [1.1, 2.2, 3.3], | ||
'B': [5.0, 6.1, 7.2], | ||
'C': [4.4, 5.5, 6.6]}, | ||
index=[2010, 2011, 2012]) | ||
|
||
expected = {0: df.copy(), | ||
1: df.copy()} | ||
expected[0].index = list('abc') | ||
expected[1].columns = list('abc') | ||
expected['index'] = expected[0] | ||
expected['columns'] = expected[1] | ||
|
||
# old signature | ||
for axis in expected: | ||
with tm.assert_produces_warning(FutureWarning): | ||
result = df.set_axis(axis, list('abc'), inplace=False) | ||
tm.assert_frame_equal(result, expected[axis]) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -234,3 +234,47 @@ def test_rename_axis_inplace(self): | |
|
||
assert no_return is None | ||
assert_series_equal(result, expected) | ||
|
||
def test_set_axis_inplace(self): | ||
# GH14636 | ||
|
||
s = Series(np.arange(4), index=[1, 3, 5, 7], dtype='int64') | ||
|
||
expected = s.copy() | ||
expected.index = list('abcd') | ||
|
||
for axis in 0, 'index': | ||
# inplace=True | ||
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. Same comment as above |
||
# The FutureWarning comes from the fact that we would like to have | ||
# inplace default to False some day | ||
for inplace, warn in (None, FutureWarning), (True, None): | ||
result = s.copy() | ||
kwargs = {'inplace': inplace} | ||
with tm.assert_produces_warning(warn): | ||
result.set_axis(list('abcd'), axis=axis, **kwargs) | ||
tm.assert_series_equal(result, expected) | ||
|
||
# inplace=False | ||
result = s.set_axis(list('abcd'), axis=0, inplace=False) | ||
tm.assert_series_equal(expected, result) | ||
|
||
# omitting the "axis" parameter | ||
with tm.assert_produces_warning(None): | ||
result = s.set_axis(list('abcd'), inplace=False) | ||
tm.assert_series_equal(result, expected) | ||
|
||
# wrong values for the "axis" parameter | ||
for axis in 2, 'foo': | ||
with tm.assert_raises_regex(ValueError, 'No axis named'): | ||
s.set_axis(list('abcd'), axis=axis, inplace=False) | ||
|
||
def test_set_axis_old_signature(self): | ||
s = Series(np.arange(4), index=[1, 3, 5, 7], dtype='int64') | ||
|
||
expected = s.copy() | ||
expected.index = list('abcd') | ||
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 for invalid axis (1 or 'foo') 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 axis='index' (should work) 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.
(done: line 266) |
||
|
||
for axis in 0, 'index': | ||
with tm.assert_produces_warning(FutureWarning): | ||
result = s.set_axis(0, list('abcd'), inplace=False) | ||
tm.assert_series_equal(result, expected) |
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 a note that the signature changed in 0.21.0
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.
(done: line 483)