Skip to content

Add support to names keyword in Index #28032

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

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,12 @@ class Index(IndexOpsMixin, PandasObject):
Otherwise, an error will be raised.
copy : bool
Make a copy of input ndarray
name : object
name : object, optional
Name to be stored in the index
tupleize_cols : bool (default: True)
When True, attempt to create a MultiIndex if possible
names : tuple of objects, optional
Names to be stored in the index (only accepts tuple of length 1)

See Also
--------
Expand Down Expand Up @@ -261,10 +263,18 @@ def __new__(
name=None,
fastpath=None,
tupleize_cols=True,
names=None,
**kwargs
):

if name is None and hasattr(data, "name"):
if names is not None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not super familiar with this part of the code but is it possible to share the length of checking of names across the index types? This already fails for a MultiIndex:

>>> pd.MultiIndex.from_tuples((('a', 'b'), ('c', 'd')), names=('a', 'b', 'c'))

ValueError: Length of names must match number of levels in MultiIndex.

So ideally could share that machinery here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a 100% sure I understood what you're saying here, but I removed the check for weather the data is a list-like.

Is that it?

if name is not None:
raise TypeError("Using name and names is unsupported")
elif len(names) > 1:
raise TypeError("names must be list-like of size 1")
# infer name from names when MultiIndex cannot be created
name = names[0]
elif hasattr(data, "name") and name is None:
name = data.name

if fastpath is not None:
Expand Down Expand Up @@ -492,9 +502,7 @@ def __new__(
# 10697
from .multi import MultiIndex

return MultiIndex.from_tuples(
data, names=name or kwargs.get("names")
)
return MultiIndex.from_tuples(data, names=names or name)
# other iterable of some kind
subarr = com.asarray_tuplesafe(data, dtype=object)
return Index(subarr, dtype=dtype, copy=copy, name=name, **kwargs)
Expand Down
19 changes: 19 additions & 0 deletions pandas/tests/indexes/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,25 @@ def test_constructor_simple_new(self, vals, dtype):
result = index._simple_new(index.values, dtype)
tm.assert_index_equal(result, index)

def test_constructor_names(self):
# test both `name` and `names`
with pytest.raises(TypeError):
idx = Index([1, 2, 3], name="a", names=("a",))

# test list-like with length > 1
with pytest.raises(TypeError):
idx = Index([1, 2, 3], names=("a", "b"))

# test using `name` for a flat `Index`
idx = Index([1, 2, 3], name="a")
assert idx.name == "a"
assert idx.names == ("a",)

# test using `names` for a flat `Index`
idx = Index([1, 2, 3], names=("a",))
assert idx.name == "a"
assert idx.names == ("a",)

@pytest.mark.parametrize(
"vals",
[
Expand Down