Skip to content

Commit 37d991c

Browse files
authored
PERF: obj_with_exclusions (#43760)
1 parent cdb725f commit 37d991c

File tree

2 files changed

+37
-13
lines changed

2 files changed

+37
-13
lines changed

pandas/core/base.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,11 @@ def _obj_with_exclusions(self):
221221
return self.obj[self._selection_list]
222222

223223
if len(self.exclusions) > 0:
224-
return self.obj.drop(self.exclusions, axis=1)
224+
# equivalent to `self.obj.drop(self.exclusions, axis=1)
225+
# but this avoids consolidating and making a copy
226+
return self.obj._drop_axis(
227+
self.exclusions, axis=1, consolidate=False, only_slice=True
228+
)
225229
else:
226230
return self.obj
227231

pandas/core/generic.py

+32-12
Original file line numberDiff line numberDiff line change
@@ -4200,7 +4200,13 @@ def drop(
42004200

42014201
@final
42024202
def _drop_axis(
4203-
self: FrameOrSeries, labels, axis, level=None, errors: str = "raise"
4203+
self: FrameOrSeries,
4204+
labels,
4205+
axis,
4206+
level=None,
4207+
errors: str = "raise",
4208+
consolidate: bool_t = True,
4209+
only_slice: bool_t = False,
42044210
) -> FrameOrSeries:
42054211
"""
42064212
Drop labels from specified axis. Used in the ``drop`` method
@@ -4214,10 +4220,13 @@ def _drop_axis(
42144220
For MultiIndex
42154221
errors : {'ignore', 'raise'}, default 'raise'
42164222
If 'ignore', suppress error and existing labels are dropped.
4223+
consolidate : bool, default True
4224+
Whether to call consolidate_inplace in the reindex_indexer call.
4225+
only_slice : bool, default False
4226+
Whether indexing along columns should be view-only.
42174227
42184228
"""
4219-
axis = self._get_axis_number(axis)
4220-
axis_name = self._get_axis_name(axis)
4229+
axis_num = self._get_axis_number(axis)
42214230
axis = self._get_axis(axis)
42224231

42234232
if axis.is_unique:
@@ -4227,7 +4236,7 @@ def _drop_axis(
42274236
new_axis = axis.drop(labels, level=level, errors=errors)
42284237
else:
42294238
new_axis = axis.drop(labels, errors=errors)
4230-
result = self.reindex(**{axis_name: new_axis})
4239+
indexer = axis.get_indexer(new_axis)
42314240

42324241
# Case for non-unique axis
42334242
else:
@@ -4236,10 +4245,10 @@ def _drop_axis(
42364245
if level is not None:
42374246
if not isinstance(axis, MultiIndex):
42384247
raise AssertionError("axis must be a MultiIndex")
4239-
indexer = ~axis.get_level_values(level).isin(labels)
4248+
mask = ~axis.get_level_values(level).isin(labels)
42404249

42414250
# GH 18561 MultiIndex.drop should raise if label is absent
4242-
if errors == "raise" and indexer.all():
4251+
if errors == "raise" and mask.all():
42434252
raise KeyError(f"{labels} not found in axis")
42444253
elif (
42454254
isinstance(axis, MultiIndex)
@@ -4249,20 +4258,31 @@ def _drop_axis(
42494258
# Set level to zero in case of MultiIndex and label is string,
42504259
# because isin can't handle strings for MultiIndexes GH#36293
42514260
# In case of tuples we get dtype object but have to use isin GH#42771
4252-
indexer = ~axis.get_level_values(0).isin(labels)
4261+
mask = ~axis.get_level_values(0).isin(labels)
42534262
else:
4254-
indexer = ~axis.isin(labels)
4263+
mask = ~axis.isin(labels)
42554264
# Check if label doesn't exist along axis
42564265
labels_missing = (axis.get_indexer_for(labels) == -1).any()
42574266
if errors == "raise" and labels_missing:
42584267
raise KeyError(f"{labels} not found in axis")
42594268

4260-
slicer = [slice(None)] * self.ndim
4261-
slicer[self._get_axis_number(axis_name)] = indexer
4269+
indexer = mask.nonzero()[0]
4270+
new_axis = axis.take(indexer)
42624271

4263-
result = self.loc[tuple(slicer)]
4272+
bm_axis = self.ndim - axis_num - 1
4273+
new_mgr = self._mgr.reindex_indexer(
4274+
new_axis,
4275+
indexer,
4276+
axis=bm_axis,
4277+
allow_dups=True,
4278+
consolidate=consolidate,
4279+
only_slice=only_slice,
4280+
)
4281+
result = self._constructor(new_mgr)
4282+
if self.ndim == 1:
4283+
result.name = self.name
42644284

4265-
return result
4285+
return result.__finalize__(self)
42664286

42674287
@final
42684288
def _update_inplace(self, result, verify_is_copy: bool_t = True) -> None:

0 commit comments

Comments
 (0)