Skip to content

Commit 10ecc1f

Browse files
author
cloudboat
committed
Change from_tuple to factorize_from_iterable
1 parent a8d626a commit 10ecc1f

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

pandas/core/indexes/multi.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
ExtensionArray,
9494
)
9595
from pandas.core.arrays.categorical import (
96+
factorize_from_iterable,
9697
factorize_from_iterables,
9798
recode_for_categories,
9899
)
@@ -2755,22 +2756,27 @@ def insert_level(
27552756
if name is lib.no_default:
27562757
name = None
27572758

2758-
if not hasattr(value, "__iter__") or isinstance(value, str):
2759-
raise ValueError("value must be an array-like object")
2760-
2761-
value = list(value)
2762-
if len(value) != len(self):
2763-
raise ValueError("Length of values must match length of index")
2759+
if not (is_list_like(value) and len(value) == len(self)):
2760+
raise ValueError(
2761+
"value must be an array-like object of the same length as self"
2762+
)
27642763

2765-
# 简洁可靠的实现
2766-
new_tuples = []
2767-
for i, tup in enumerate(self):
2768-
new_tuple = tup[:position] + (value[i],) + tup[position:]
2769-
new_tuples.append(new_tuple)
2764+
if all(val is None for val in value):
2765+
new_level = Index([], dtype="object")
2766+
new_codes = [-1] * len(value)
2767+
else:
2768+
new_codes, new_level = factorize_from_iterable(value)
27702769

2770+
new_levels = self.levels[:position] + [new_level] + self.levels[position:]
2771+
new_codes_list = self.codes[:position] + [new_codes] + self.codes[position:]
27712772
new_names = self.names[:position] + [name] + self.names[position:]
27722773

2773-
return MultiIndex.from_tuples(new_tuples, names=new_names)
2774+
return MultiIndex(
2775+
levels=new_levels,
2776+
codes=new_codes_list,
2777+
names=new_names,
2778+
verify_integrity=False,
2779+
)
27742780

27752781
def _reorder_ilevels(self, order) -> MultiIndex:
27762782
if len(order) != self.nlevels:

pandas/tests/indexes/multi/test_insert_level.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,17 @@ def test_insert_level_basic(position, value, name, expected_tuples, expected_nam
108108
[
109109
(5, ["invalid"] * 3, "position must be between"),
110110
(-1, ["invalid"] * 3, "position must be between"),
111-
(1, ["too", "few"], "Length of values must match"),
111+
(
112+
1,
113+
["too", "few"],
114+
"value must be an array-like object of the same length as self",
115+
),
112116
(3, ["value"] * 3, "position must be between"),
113-
(0, "scalar_value", "value must be an array-like object"),
117+
(
118+
0,
119+
"scalar_value",
120+
"value must be an array-like object of the same length as self",
121+
),
114122
],
115123
)
116124
def test_insert_level_error_cases(position, value, expected_error):

0 commit comments

Comments
 (0)