Skip to content

Commit 1367a26

Browse files
committed
putmask to use split_and_operate
1 parent e7e0cfb commit 1367a26

File tree

1 file changed

+31
-44
lines changed

1 file changed

+31
-44
lines changed

pandas/core/internals.py

+31-44
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ def fillna(self, value, limit=None, inplace=False, downcast=None,
398398
return self if inplace else self.copy()
399399

400400
# operate column-by-column
401-
def f(m, v):
401+
def f(m, v, i):
402402

403403
# try again with a compatible block
404404
block = self.coerce_to_target_dtype(original_value)
@@ -411,14 +411,14 @@ def f(m, v):
411411

412412
def split_and_operate(self, mask, f, inplace):
413413
"""
414-
split the block per-column. if masking
415-
that block, promot if needed, then
416-
apply the function f
414+
split the block per-column, and apply the callable f
415+
per-column, return a new block for each. Handle
416+
masking which will not change a block unless needed.
417417
418418
Parameters
419419
----------
420420
mask : 2-d boolean mask
421-
f : function accepting (1-mask, 1-d values)
421+
f : callable accepting (1d-mask, 1d values, indexer)
422422
inplace : boolean
423423
424424
Returns
@@ -436,19 +436,19 @@ def make_a_block(nv, ref_loc):
436436
else:
437437
# Put back the dimension that was taken from it and make
438438
# a block out of the result.
439-
block = self.make_block(values=nv[np.newaxis],
440-
placement=[ref_loc], fastpath=True)
439+
nv = _block_shape(nv, ndim=self.ndim)
440+
block = self.make_block(values=nv,
441+
placement=ref_loc, fastpath=True)
441442
return block
442443

443444
# ndim == 1
444445
if self.ndim == 1:
445-
446446
if mask.any():
447-
nv = f(mask, new_values)
447+
nv = f(mask, new_values, None)
448448
else:
449449
nv = new_values if inplace else new_values.copy()
450-
block = make_a_block(nv, 0)
451-
return block
450+
block = make_a_block(nv, self.mgr_locs)
451+
return [block]
452452

453453
# ndim > 1
454454
new_blocks = []
@@ -458,11 +458,11 @@ def make_a_block(nv, ref_loc):
458458

459459
# need a new block
460460
if m.any():
461-
nv = f(m, v)
461+
nv = f(m, v, i)
462462
else:
463463
nv = v if inplace else v.copy()
464464

465-
block = make_a_block(nv, ref_loc)
465+
block = make_a_block(nv, [ref_loc])
466466
new_blocks.append(block)
467467

468468
return new_blocks
@@ -960,44 +960,31 @@ def putmask(self, mask, new, align=True, inplace=False, axis=0,
960960
new_shape.insert(axis, 1)
961961
new = new.reshape(tuple(new_shape))
962962

963-
# TODO(jreback)
964-
# use split_and_operate
965-
966-
# need to go column by column
967-
new_blocks = []
968-
if self.ndim > 1:
969-
for i, ref_loc in enumerate(self.mgr_locs):
970-
m = mask[i]
971-
v = new_values[i]
972-
973-
# need a new block
974-
if m.any():
975-
if isinstance(new, np.ndarray):
976-
n = np.squeeze(new[i % new.shape[0]])
977-
else:
978-
n = np.array(new)
979-
980-
# type of the new block
981-
dtype, _ = maybe_promote(n.dtype)
963+
# operate column-by-column
964+
def f(m, v, i):
982965

983-
# we need to explicitly astype here to make a copy
984-
n = n.astype(dtype)
966+
# TODO(jreback)
967+
# see if we can use coerce_to_target_dtype here instead
985968

986-
nv = _putmask_smart(v, m, n)
969+
if i is None:
970+
# ndim==1 case.
971+
n = new
972+
else:
973+
if isinstance(new, np.ndarray):
974+
n = np.squeeze(new[i % new.shape[0]])
987975
else:
988-
nv = v if inplace else v.copy()
976+
n = np.array(new)
989977

990-
# Put back the dimension that was taken from it and make
991-
# a block out of the result.
992-
block = self.make_block(values=nv[np.newaxis],
993-
placement=[ref_loc], fastpath=True)
978+
# type of the new block
979+
dtype, _ = maybe_promote(n.dtype)
994980

995-
new_blocks.append(block)
981+
# we need to explicitly astype here to make a copy
982+
n = n.astype(dtype)
996983

997-
else:
998-
nv = _putmask_smart(new_values, mask, new)
999-
new_blocks.append(self.make_block(values=nv, fastpath=True))
984+
nv = _putmask_smart(v, m, n)
985+
return nv
1000986

987+
new_blocks = self.split_and_operate(mask, f, inplace)
1001988
return new_blocks
1002989

1003990
if inplace:

0 commit comments

Comments
 (0)