@@ -397,12 +397,75 @@ def fillna(self, value, limit=None, inplace=False, downcast=None,
397
397
if not mask .any ():
398
398
return self if inplace else self .copy ()
399
399
400
- # try again with a compatible block
401
- block = self .coerce_to_target_dtype (original_value )
402
- return block .fillna (original_value ,
403
- limit = limit ,
404
- inplace = inplace ,
405
- downcast = False )
400
+ # operate column-by-column
401
+ def f (m , v ):
402
+
403
+ # try again with a compatible block
404
+ block = self .coerce_to_target_dtype (original_value )
405
+ return block .fillna (original_value ,
406
+ limit = limit ,
407
+ inplace = inplace ,
408
+ downcast = False )
409
+
410
+ return self .split_and_operate (mask , f , inplace )
411
+
412
+ def split_and_operate (self , mask , f , inplace ):
413
+ """
414
+ split the block per-column. if masking
415
+ that block, promot if needed, then
416
+ apply the function f
417
+
418
+ Parameters
419
+ ----------
420
+ mask : 2-d boolean mask
421
+ f : function accepting (1-mask, 1-d values)
422
+ inplace : boolean
423
+
424
+ Returns
425
+ -------
426
+ list of blocks
427
+ """
428
+
429
+ new_values = self .values
430
+
431
+ def make_a_block (nv , ref_loc ):
432
+ if isinstance (nv , Block ):
433
+ block = nv
434
+ elif isinstance (nv , list ):
435
+ block = nv [0 ]
436
+ else :
437
+ # Put back the dimension that was taken from it and make
438
+ # a block out of the result.
439
+ block = self .make_block (values = nv [np .newaxis ],
440
+ placement = [ref_loc ], fastpath = True )
441
+ return block
442
+
443
+ # ndim == 1
444
+ if self .ndim == 1 :
445
+
446
+ if mask .any ():
447
+ nv = f (mask , new_values )
448
+ else :
449
+ nv = new_values if inplace else new_values .copy ()
450
+ block = make_a_block (nv , 0 )
451
+ return block
452
+
453
+ # ndim > 1
454
+ new_blocks = []
455
+ for i , ref_loc in enumerate (self .mgr_locs ):
456
+ m = mask [i ]
457
+ v = new_values [i ]
458
+
459
+ # need a new block
460
+ if m .any ():
461
+ nv = f (m , v )
462
+ else :
463
+ nv = v if inplace else v .copy ()
464
+
465
+ block = make_a_block (nv , ref_loc )
466
+ new_blocks .append (block )
467
+
468
+ return new_blocks
406
469
407
470
def _maybe_downcast (self , blocks , downcast = None ):
408
471
@@ -899,6 +962,9 @@ def putmask(self, mask, new, align=True, inplace=False, axis=0,
899
962
new_shape .insert (axis , 1 )
900
963
new = new .reshape (tuple (new_shape ))
901
964
965
+ # TODO(jreback)
966
+ # use split_and_operate
967
+
902
968
# need to go column by column
903
969
new_blocks = []
904
970
if self .ndim > 1 :
0 commit comments