-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
ENH: Implement dict-like support for rename and set_names in MultiIndex #38126
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 7 commits
d95308f
d1ec051
da475c7
00c0134
de76243
dbfce8d
0f4d773
a56a04b
dd49505
b346427
2df5ccf
02c7909
ad5fe75
0f5f6e1
b4767d2
c9f7264
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 |
---|---|---|
|
@@ -73,6 +73,7 @@ | |
ABCSeries, | ||
ABCTimedeltaIndex, | ||
) | ||
from pandas.core.dtypes.inference import is_dict_like | ||
from pandas.core.dtypes.missing import array_equivalent, isna | ||
|
||
from pandas.core import missing, ops | ||
|
@@ -1319,11 +1320,18 @@ def set_names(self, names, level=None, inplace: bool = False): | |
|
||
Parameters | ||
---------- | ||
names : label or list of label | ||
|
||
names : label or list of label or dict-like for MultiIndex | ||
Name(s) to set. | ||
|
||
.. versionchanged:: 1.2.0 | ||
|
||
level : int, label or list of int or label, optional | ||
If the index is a MultiIndex, level(s) to set (None for all | ||
levels). Otherwise level must be None. | ||
If the index is a MultiIndex and names is not dict-like, level(s) to set | ||
jreback marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(None for all levels). Otherwise level must be None. | ||
|
||
.. versionchanged:: 1.2.0 | ||
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. 1.3 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 |
||
|
||
inplace : bool, default False | ||
Modifies the object directly, instead of creating a new Index or | ||
MultiIndex. | ||
|
@@ -1366,6 +1374,15 @@ def set_names(self, names, level=None, inplace: bool = False): | |
( 'cobra', 2018), | ||
( 'cobra', 2019)], | ||
names=['species', 'year']) | ||
|
||
When renaming levels through a dictionary no level can't be passed. | ||
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. When renaming levels with a dict, levels can not be passed. 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 |
||
|
||
>>> idx.set_names({'kind': 'snake'}) | ||
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 comment on this example (skip a line) 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 |
||
MultiIndex([('python', 2018), | ||
('python', 2019), | ||
( 'cobra', 2018), | ||
( 'cobra', 2019)], | ||
names=['snake', 'year']) | ||
""" | ||
if level is not None and not isinstance(self, ABCMultiIndex): | ||
raise ValueError("Level must be None for non-MultiIndex") | ||
|
@@ -1376,6 +1393,12 @@ def set_names(self, names, level=None, inplace: bool = False): | |
if not is_list_like(names) and level is None and self.nlevels > 1: | ||
raise TypeError("Must pass list-like as `names`.") | ||
|
||
if is_dict_like(names) and not isinstance(self, ABCMultiIndex): | ||
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. all of these conditions can be if/elif 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. Wanted to be consistent with the existing conditions, changed them to elif |
||
raise TypeError("Can only pass dict-like as `names` for MultiIndex.") | ||
jreback marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if is_dict_like(names) and level is not None: | ||
raise TypeError("Can not pass level when passing dict-like as `names`.") | ||
|
||
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. doesn't this hit a dict-like names? 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. Yikes, yes you are right. have not though about dict like names. Removed this |
||
if not is_list_like(names): | ||
names = [names] | ||
if level is not None and not is_list_like(level): | ||
|
@@ -1385,6 +1408,16 @@ def set_names(self, names, level=None, inplace: bool = False): | |
idx = self | ||
else: | ||
idx = self._shallow_copy() | ||
|
||
if isinstance(self, ABCMultiIndex) and is_dict_like(names): | ||
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 comment on what this condition is doing? 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 |
||
# Transform dict to list of new names and corresponding levels | ||
level, names_adjusted = [], [] | ||
for i, name in enumerate(self.names): | ||
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. see my comment above i think this condition needs to be on L1402 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. Moved it up a bit and added level is None |
||
if name in names.keys(): | ||
level.append(i) | ||
names_adjusted.append(names[name]) | ||
names = names_adjusted | ||
|
||
idx._set_names(names, level=level) | ||
if not inplace: | ||
return idx | ||
|
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.
change to 1.3
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.
Thx
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