Skip to content

Commit 30b2750

Browse files
committed
fix for pandas-dev#60695 fix Series constructor dropping key levels when keys have varying entry counts
1 parent af99a25 commit 30b2750

File tree

1 file changed

+17
-32
lines changed

1 file changed

+17
-32
lines changed

pandas/core/indexes/multi.py

+17-32
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
Hashable,
88
Iterable,
99
Sequence,
10+
List,
1011
)
1112
from functools import wraps
1213
from sys import getsizeof
@@ -15,6 +16,7 @@
1516
Any,
1617
Literal,
1718
cast,
19+
ArrayLike,
1820
)
1921
import warnings
2022

@@ -517,7 +519,7 @@ def from_arrays(
517519
)
518520

519521
@classmethod
520-
@names_compat
522+
@doc(doc_create_index)
521523
def from_tuples(
522524
cls,
523525
tuples: Iterable[tuple[Hashable, ...]],
@@ -529,41 +531,24 @@ def from_tuples(
529531
"""
530532
if not is_list_like(tuples):
531533
raise TypeError("Input must be a list / sequence of tuple-likes.")
532-
533-
if is_iterator(tuples):
534-
tuples = list(tuples)
535-
536-
tuples = cast(Collection[tuple[Hashable, ...]], tuples)
537-
538-
# handling the empty tuple cases
539-
if len(tuples) and all(isinstance(e, tuple) and not e for e in tuples):
540-
codes = [np.zeros(len(tuples))]
541-
levels = [Index(com.asarray_tuplesafe(tuples, dtype=np.dtype("object")))]
542-
return cls(
543-
levels=levels,
544-
codes=codes,
545-
sortorder=sortorder,
546-
names=names,
547-
verify_integrity=False,
548-
)
549534

550-
arrays: list[Sequence[Hashable]]
551-
if len(tuples) == 0:
535+
if isinstance(tuples, (list, tuple)) and len(tuples) == 0:
552536
if names is None:
553537
raise TypeError("Cannot infer number of levels from empty list")
554-
# error: Argument 1 to "len" has incompatible type "Hashable";
555-
# expected "Sized"
556-
arrays = [[]] * len(names) # type: ignore[arg-type]
557-
elif isinstance(tuples, (np.ndarray, Index)):
558-
if isinstance(tuples, Index):
559-
tuples = np.asarray(tuples._values)
560-
561-
arrays = list(lib.tuples_to_object_array(tuples).T)
562-
elif isinstance(tuples, list):
563-
arrays = list(lib.to_object_array_tuples(tuples).T)
538+
names_seq = cast(Sequence[Hashable], names)
539+
arrays: List[ArrayLike] = [[]] * len(names_seq)
540+
return cls.from_arrays(arrays, sortorder=sortorder, names=names)
541+
542+
# Convert to list and normalize
543+
tuples_list = [t if isinstance(t, tuple) else (t,) for t in tuples]
544+
if not tuples_list:
545+
arrays = []
564546
else:
565-
arrs = zip(*tuples)
566-
arrays = cast(list[Sequence[Hashable]], arrs)
547+
max_length = max(len(t) for t in tuples_list)
548+
result_tuples = [
549+
t + (np.nan,) * (max_length - len(t)) for t in tuples_list
550+
]
551+
arrays = list(lib.to_object_array_tuples(result_tuples).T)
567552

568553
return cls.from_arrays(arrays, sortorder=sortorder, names=names)
569554

0 commit comments

Comments
 (0)