Skip to content

Commit e9420ad

Browse files
jbrockmendelyehoshuadimarsky
authored andcommitted
REF: make Block.delete return a new Block (pandas-dev#45689)
1 parent 0a76027 commit e9420ad

File tree

3 files changed

+42
-38
lines changed

3 files changed

+42
-38
lines changed

pandas/core/internals/blocks.py

+9-20
Original file line numberDiff line numberDiff line change
@@ -380,23 +380,19 @@ def set_inplace(self, locs, values: ArrayLike) -> None:
380380
"""
381381
self.values[locs] = values
382382

383-
def delete(self, loc) -> None:
383+
def delete(self, loc) -> Block:
384384
"""
385-
Delete given loc(-s) from block in-place.
385+
Return a new Block with the given loc(s) deleted.
386386
"""
387387
# Argument 1 to "delete" has incompatible type "Union[ndarray[Any, Any],
388388
# ExtensionArray]"; expected "Union[_SupportsArray[dtype[Any]],
389389
# Sequence[_SupportsArray[dtype[Any]]], Sequence[Sequence
390390
# [_SupportsArray[dtype[Any]]]], Sequence[Sequence[Sequence[
391391
# _SupportsArray[dtype[Any]]]]], Sequence[Sequence[Sequence[Sequence[
392392
# _SupportsArray[dtype[Any]]]]]]]" [arg-type]
393-
self.values = np.delete(self.values, loc, 0) # type: ignore[arg-type]
394-
self.mgr_locs = self._mgr_locs.delete(loc)
395-
try:
396-
self._cache.clear()
397-
except AttributeError:
398-
# _cache not yet initialized
399-
pass
393+
values = np.delete(self.values, loc, 0) # type: ignore[arg-type]
394+
mgr_locs = self._mgr_locs.delete(loc)
395+
return type(self)(values, placement=mgr_locs, ndim=self.ndim)
400396

401397
@final
402398
def apply(self, func, **kwargs) -> list[Block]:
@@ -1504,18 +1500,11 @@ def fillna(
15041500

15051501
return [self.make_block_same_class(values=new_values)]
15061502

1507-
def delete(self, loc) -> None:
1508-
"""
1509-
Delete given loc(-s) from block in-place.
1510-
"""
1503+
def delete(self, loc) -> Block:
15111504
# This will be unnecessary if/when __array_function__ is implemented
1512-
self.values = self.values.delete(loc)
1513-
self.mgr_locs = self._mgr_locs.delete(loc)
1514-
try:
1515-
self._cache.clear()
1516-
except AttributeError:
1517-
# _cache not yet initialized
1518-
pass
1505+
values = self.values.delete(loc)
1506+
mgr_locs = self._mgr_locs.delete(loc)
1507+
return type(self)(values, placement=mgr_locs, ndim=self.ndim)
15191508

15201509
@cache_readonly
15211510
def array_values(self) -> ExtensionArray:

pandas/core/internals/managers.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -1133,8 +1133,12 @@ def value_getitem(placement):
11331133
if len(val_locs) == len(blk.mgr_locs):
11341134
removed_blknos.append(blkno_l)
11351135
else:
1136-
blk.delete(blk_locs)
1137-
self._blklocs[blk.mgr_locs.indexer] = np.arange(len(blk))
1136+
nb = blk.delete(blk_locs)
1137+
blocks_tup = (
1138+
self.blocks[:blkno_l] + (nb,) + self.blocks[blkno_l + 1 :]
1139+
)
1140+
self.blocks = blocks_tup
1141+
self._blklocs[nb.mgr_locs.indexer] = np.arange(len(nb))
11381142

11391143
if len(removed_blknos):
11401144
# Remove blocks & update blknos accordingly
@@ -1869,8 +1873,10 @@ def idelete(self, indexer) -> SingleBlockManager:
18691873
18701874
Ensures that self.blocks doesn't become empty.
18711875
"""
1872-
self._block.delete(indexer)
1876+
nb = self._block.delete(indexer)
1877+
self.blocks = (nb,)
18731878
self.axes[0] = self.axes[0].delete(indexer)
1879+
self._cache.clear()
18741880
return self
18751881

18761882
def fast_xs(self, loc):

pandas/tests/internals/test_internals.py

+24-15
Original file line numberDiff line numberDiff line change
@@ -285,27 +285,36 @@ def test_copy(self):
285285

286286
def test_delete(self):
287287
newb = self.fblock.copy()
288-
newb.delete(0)
289-
assert isinstance(newb.mgr_locs, BlockPlacement)
288+
locs = newb.mgr_locs
289+
nb = newb.delete(0)
290+
assert newb.mgr_locs is locs
291+
292+
assert nb is not newb
293+
290294
tm.assert_numpy_array_equal(
291-
newb.mgr_locs.as_array, np.array([2, 4], dtype=np.intp)
295+
nb.mgr_locs.as_array, np.array([2, 4], dtype=np.intp)
292296
)
293-
assert (newb.values[0] == 1).all()
297+
assert not (newb.values[0] == 1).all()
298+
assert (nb.values[0] == 1).all()
294299

295300
newb = self.fblock.copy()
296-
newb.delete(1)
297-
assert isinstance(newb.mgr_locs, BlockPlacement)
301+
locs = newb.mgr_locs
302+
nb = newb.delete(1)
303+
assert newb.mgr_locs is locs
304+
298305
tm.assert_numpy_array_equal(
299-
newb.mgr_locs.as_array, np.array([0, 4], dtype=np.intp)
306+
nb.mgr_locs.as_array, np.array([0, 4], dtype=np.intp)
300307
)
301-
assert (newb.values[1] == 2).all()
308+
assert not (newb.values[1] == 2).all()
309+
assert (nb.values[1] == 2).all()
302310

303311
newb = self.fblock.copy()
304-
newb.delete(2)
312+
locs = newb.mgr_locs
313+
nb = newb.delete(2)
305314
tm.assert_numpy_array_equal(
306-
newb.mgr_locs.as_array, np.array([0, 2], dtype=np.intp)
315+
nb.mgr_locs.as_array, np.array([0, 2], dtype=np.intp)
307316
)
308-
assert (newb.values[1] == 1).all()
317+
assert (nb.values[1] == 1).all()
309318

310319
newb = self.fblock.copy()
311320

@@ -319,15 +328,15 @@ def test_delete_datetimelike(self):
319328
blk = df._mgr.blocks[0]
320329
assert isinstance(blk.values, TimedeltaArray)
321330

322-
blk.delete(1)
323-
assert isinstance(blk.values, TimedeltaArray)
331+
nb = blk.delete(1)
332+
assert isinstance(nb.values, TimedeltaArray)
324333

325334
df = DataFrame(arr.view("M8[ns]"))
326335
blk = df._mgr.blocks[0]
327336
assert isinstance(blk.values, DatetimeArray)
328337

329-
blk.delete([1, 3])
330-
assert isinstance(blk.values, DatetimeArray)
338+
nb = blk.delete([1, 3])
339+
assert isinstance(nb.values, DatetimeArray)
331340

332341
def test_split(self):
333342
# GH#37799

0 commit comments

Comments
 (0)