|
93 | 93 | ExtensionArray, |
94 | 94 | ) |
95 | 95 | from pandas.core.arrays.categorical import ( |
| 96 | + factorize_from_iterable, |
96 | 97 | factorize_from_iterables, |
97 | 98 | recode_for_categories, |
98 | 99 | ) |
@@ -2755,22 +2756,27 @@ def insert_level( |
2755 | 2756 | if name is lib.no_default: |
2756 | 2757 | name = None |
2757 | 2758 |
|
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 | + ) |
2764 | 2763 |
|
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) |
2770 | 2769 |
|
| 2770 | + new_levels = self.levels[:position] + [new_level] + self.levels[position:] |
| 2771 | + new_codes_list = self.codes[:position] + [new_codes] + self.codes[position:] |
2771 | 2772 | new_names = self.names[:position] + [name] + self.names[position:] |
2772 | 2773 |
|
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 | + ) |
2774 | 2780 |
|
2775 | 2781 | def _reorder_ilevels(self, order) -> MultiIndex: |
2776 | 2782 | if len(order) != self.nlevels: |
|
0 commit comments