@@ -175,7 +175,13 @@ def _indexer_and_to_sort(
175
175
codes = list (self .index .codes )
176
176
if not self .sort :
177
177
# Create new codes considering that labels are already sorted
178
- codes = [factorize (code )[0 ] for code in codes ]
178
+ # Make sure to preserve the -1 values before factorizing
179
+ codes = []
180
+ for code in self .index .codes :
181
+ mask = code != - 1
182
+ factorized = np .full_like (code , - 1 )
183
+ factorized [mask ] = factorize (code [mask ])[0 ]
184
+ codes .append (factorized )
179
185
levs = list (self .index .levels )
180
186
to_sort = codes [:v ] + codes [v + 1 :] + [codes [v ]]
181
187
sizes = tuple (len (x ) for x in levs [:v ] + levs [v + 1 :] + [levs [v ]])
@@ -194,9 +200,15 @@ def sorted_labels(self) -> list[np.ndarray]:
194
200
return to_sort
195
201
196
202
def _make_sorted_values (self , values : np .ndarray ) -> np .ndarray :
197
- indexer , _ = self ._indexer_and_to_sort
198
- sorted_values = algos .take_nd (values , indexer , axis = 0 )
199
- return sorted_values
203
+ if self .sort :
204
+ indexer , _ = self ._indexer_and_to_sort
205
+ sorted_values = algos .take_nd (values , indexer , axis = 0 )
206
+ return sorted_values
207
+ level_sizes = tuple (len (level ) for level in self .new_index_levels )
208
+ group_ids = get_group_index (
209
+ self .sorted_labels [:- 1 ], level_sizes , sort = False , xnull = False
210
+ )
211
+ return values [np .argsort (group_ids , kind = "mergesort" )]
200
212
201
213
def _make_selectors (self ) -> None :
202
214
new_levels = self .new_index_levels
@@ -581,7 +593,6 @@ def _unstack_frame(
581
593
unstacker = _Unstacker (
582
594
obj .index , level = level , constructor = obj ._constructor , sort = sort
583
595
)
584
-
585
596
if not obj ._can_fast_transpose :
586
597
mgr = obj ._mgr .unstack (unstacker , fill_value = fill_value )
587
598
return obj ._constructor_from_mgr (mgr , axes = mgr .axes )
0 commit comments