2
2
import itertools
3
3
from typing import (
4
4
Any ,
5
+ Callable ,
5
6
DefaultDict ,
6
7
Dict ,
7
8
List ,
@@ -324,18 +325,44 @@ def _verify_integrity(self) -> None:
324
325
f"tot_items: { tot_items } "
325
326
)
326
327
327
- def reduce (self : T , func ) -> T :
328
+ def reduce (
329
+ self : T , func : Callable , ignore_failures : bool = False
330
+ ) -> Tuple [T , np .ndarray ]:
331
+ """
332
+ Apply reduction function blockwise, returning a single-row BlockManager.
333
+
334
+ Parameters
335
+ ----------
336
+ func : reduction function
337
+ ignore_failures : bool, default False
338
+ Whether to drop blocks where func raises TypeError.
339
+
340
+ Returns
341
+ -------
342
+ BlockManager
343
+ np.ndarray
344
+ Indexer of mgr_locs that are retained.
345
+ """
328
346
# If 2D, we assume that we're operating column-wise
329
347
assert self .ndim == 2
330
348
331
349
res_blocks : List [Block ] = []
332
350
for blk in self .blocks :
333
- nbs = blk .reduce (func )
351
+ nbs = blk .reduce (func , ignore_failures )
334
352
res_blocks .extend (nbs )
335
353
336
- index = Index ([0 ]) # placeholder
337
- new_mgr = BlockManager .from_blocks (res_blocks , [self .items , index ])
338
- return new_mgr
354
+ index = Index ([None ]) # placeholder
355
+ if ignore_failures :
356
+ if res_blocks :
357
+ indexer = np .concatenate ([blk .mgr_locs .as_array for blk in res_blocks ])
358
+ new_mgr = self ._combine (res_blocks , copy = False , index = index )
359
+ else :
360
+ indexer = []
361
+ new_mgr = type (self ).from_blocks ([], [Index ([]), index ])
362
+ else :
363
+ indexer = np .arange (self .shape [0 ])
364
+ new_mgr = type (self ).from_blocks (res_blocks , [self .items , index ])
365
+ return new_mgr , indexer
339
366
340
367
def operate_blockwise (self , other : "BlockManager" , array_op ) -> "BlockManager" :
341
368
"""
@@ -698,7 +725,9 @@ def get_numeric_data(self, copy: bool = False) -> "BlockManager":
698
725
"""
699
726
return self ._combine ([b for b in self .blocks if b .is_numeric ], copy )
700
727
701
- def _combine (self : T , blocks : List [Block ], copy : bool = True ) -> T :
728
+ def _combine (
729
+ self : T , blocks : List [Block ], copy : bool = True , index : Optional [Index ] = None
730
+ ) -> T :
702
731
""" return a new manager with the blocks """
703
732
if len (blocks ) == 0 :
704
733
return self .make_empty ()
@@ -714,6 +743,8 @@ def _combine(self: T, blocks: List[Block], copy: bool = True) -> T:
714
743
new_blocks .append (b )
715
744
716
745
axes = list (self .axes )
746
+ if index is not None :
747
+ axes [- 1 ] = index
717
748
axes [0 ] = self .items .take (indexer )
718
749
719
750
return type (self ).from_blocks (new_blocks , axes )
0 commit comments