@@ -1252,7 +1252,7 @@ def _unstack(
1252
1252
unstacker ,
1253
1253
fill_value ,
1254
1254
new_placement : npt .NDArray [np .intp ],
1255
- allow_fill : bool ,
1255
+ needs_masking : npt . NDArray [ np . bool_ ] ,
1256
1256
):
1257
1257
"""
1258
1258
Return a list of unstacked blocks of self
@@ -1264,6 +1264,7 @@ def _unstack(
1264
1264
Only used in ExtensionBlock._unstack
1265
1265
new_placement : np.ndarray[np.intp]
1266
1266
allow_fill : bool
1267
+ needs_masking : np.ndarray[bool]
1267
1268
1268
1269
Returns
1269
1270
-------
@@ -1673,7 +1674,7 @@ def _unstack(
1673
1674
unstacker ,
1674
1675
fill_value ,
1675
1676
new_placement : npt .NDArray [np .intp ],
1676
- allow_fill : bool ,
1677
+ needs_masking : npt . NDArray [ np . bool_ ] ,
1677
1678
):
1678
1679
# ExtensionArray-safe unstack.
1679
1680
# We override ObjectBlock._unstack, which unstacks directly on the
@@ -1692,14 +1693,20 @@ def _unstack(
1692
1693
new_values = new_values .T [mask ]
1693
1694
new_placement = new_placement [mask ]
1694
1695
1696
+ # needs_masking[i] calculated once in BlockManager.unstack tells
1697
+ # us if there are any -1s in the relevant indices. When False,
1698
+ # that allows us to go through a faster path in 'take', among
1699
+ # other things avoiding e.g. Categorical._validate_scalar.
1695
1700
blocks = [
1696
1701
# TODO: could cast to object depending on fill_value?
1697
1702
type (self )(
1698
- self .values .take (indices , allow_fill = allow_fill , fill_value = fill_value ),
1703
+ self .values .take (
1704
+ indices , allow_fill = needs_masking [i ], fill_value = fill_value
1705
+ ),
1699
1706
BlockPlacement (place ),
1700
1707
ndim = 2 ,
1701
1708
)
1702
- for indices , place in zip (new_values , new_placement )
1709
+ for i , ( indices , place ) in enumerate ( zip (new_values , new_placement ) )
1703
1710
]
1704
1711
return blocks , mask
1705
1712
0 commit comments