Skip to content

Commit c1673cf

Browse files
jrebackjbrockmendel
authored andcommitted
CLN/PERF: remove gc.collect from the setting_with_copy checks as not needed (#27031)
* CLN/PERF: remove gc.collect from the setting_with_copy checks as not needed * fixup whatsnew * add asv
1 parent 1452e71 commit c1673cf

File tree

3 files changed

+57
-48
lines changed

3 files changed

+57
-48
lines changed

asv_bench/benchmarks/indexing.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pandas import (Series, DataFrame, MultiIndex,
66
Int64Index, UInt64Index, Float64Index,
77
IntervalIndex, CategoricalIndex,
8-
IndexSlice, concat, date_range)
8+
IndexSlice, concat, date_range, option_context)
99

1010

1111
class NumericSeriesIndexing:
@@ -335,4 +335,20 @@ def time_assign_with_setitem(self):
335335
self.df[i] = np.random.randn(self.N)
336336

337337

338+
class ChainIndexing:
339+
340+
params = [None, 'warn']
341+
param_names = ['mode']
342+
343+
def setup(self, mode):
344+
self.N = 1000000
345+
346+
def time_chained_indexing(self, mode):
347+
with warnings.catch_warnings(record=True):
348+
with option_context('mode.chained_assignment', mode):
349+
df = DataFrame({'A': np.arange(self.N), 'B': 'foo'})
350+
df2 = df[df.A > self.N // 2]
351+
df2['C'] = 1.0
352+
353+
338354
from .pandas_vb_common import setup # noqa: F401

doc/source/whatsnew/v0.25.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ Performance Improvements
579579
- Improved performance of :attr:`IntervalIndex.is_unique` by removing conversion to ``MultiIndex`` (:issue:`24813`)
580580
- Restored performance of :meth:`DatetimeIndex.__iter__` by re-enabling specialized code path (:issue:`26702`)
581581
- Improved performance when building :class:`MultiIndex` with at least one :class:`CategoricalIndex` level (:issue:`22044`)
582+
- Improved performance by removing the need for a garbage collect when checking for ``SettingWithCopyWarning`` (:issue:`27031`)
582583

583584
.. _whatsnew_0250.bug_fixes:
584585

pandas/core/generic.py

+39-47
Original file line numberDiff line numberDiff line change
@@ -3263,58 +3263,50 @@ def _check_setitem_copy(self, stacklevel=4, t='setting', force=False):
32633263
32643264
"""
32653265

3266-
if force or self._is_copy:
3266+
# return early if the check is not needed
3267+
if not (force or self._is_copy):
3268+
return
32673269

3268-
value = config.get_option('mode.chained_assignment')
3269-
if value is None:
3270-
return
3271-
3272-
# see if the copy is not actually referred; if so, then dissolve
3273-
# the copy weakref
3274-
try:
3275-
gc.collect(2)
3276-
if not gc.get_referents(self._is_copy()):
3277-
self._is_copy = None
3278-
return
3279-
except Exception:
3280-
pass
3270+
value = config.get_option('mode.chained_assignment')
3271+
if value is None:
3272+
return
32813273

3282-
# we might be a false positive
3283-
try:
3284-
if self._is_copy().shape == self.shape:
3285-
self._is_copy = None
3286-
return
3287-
except Exception:
3288-
pass
3274+
# see if the copy is not actually referred; if so, then dissolve
3275+
# the copy weakref
3276+
if self._is_copy is not None and not isinstance(self._is_copy, str):
3277+
r = self._is_copy()
3278+
if not gc.get_referents(r) or r.shape == self.shape:
3279+
self._is_copy = None
3280+
return
32893281

3290-
# a custom message
3291-
if isinstance(self._is_copy, str):
3292-
t = self._is_copy
3282+
# a custom message
3283+
if isinstance(self._is_copy, str):
3284+
t = self._is_copy
32933285

3294-
elif t == 'referant':
3295-
t = ("\n"
3296-
"A value is trying to be set on a copy of a slice from a "
3297-
"DataFrame\n\n"
3298-
"See the caveats in the documentation: "
3299-
"http://pandas.pydata.org/pandas-docs/stable/user_guide/"
3300-
"indexing.html#returning-a-view-versus-a-copy"
3301-
)
3286+
elif t == 'referant':
3287+
t = ("\n"
3288+
"A value is trying to be set on a copy of a slice from a "
3289+
"DataFrame\n\n"
3290+
"See the caveats in the documentation: "
3291+
"http://pandas.pydata.org/pandas-docs/stable/user_guide/"
3292+
"indexing.html#returning-a-view-versus-a-copy"
3293+
)
33023294

3303-
else:
3304-
t = ("\n"
3305-
"A value is trying to be set on a copy of a slice from a "
3306-
"DataFrame.\n"
3307-
"Try using .loc[row_indexer,col_indexer] = value "
3308-
"instead\n\nSee the caveats in the documentation: "
3309-
"http://pandas.pydata.org/pandas-docs/stable/user_guide/"
3310-
"indexing.html#returning-a-view-versus-a-copy"
3311-
)
3312-
3313-
if value == 'raise':
3314-
raise com.SettingWithCopyError(t)
3315-
elif value == 'warn':
3316-
warnings.warn(t, com.SettingWithCopyWarning,
3317-
stacklevel=stacklevel)
3295+
else:
3296+
t = ("\n"
3297+
"A value is trying to be set on a copy of a slice from a "
3298+
"DataFrame.\n"
3299+
"Try using .loc[row_indexer,col_indexer] = value "
3300+
"instead\n\nSee the caveats in the documentation: "
3301+
"http://pandas.pydata.org/pandas-docs/stable/user_guide/"
3302+
"indexing.html#returning-a-view-versus-a-copy"
3303+
)
3304+
3305+
if value == 'raise':
3306+
raise com.SettingWithCopyError(t)
3307+
elif value == 'warn':
3308+
warnings.warn(t, com.SettingWithCopyWarning,
3309+
stacklevel=stacklevel)
33183310

33193311
def __delitem__(self, key):
33203312
"""

0 commit comments

Comments
 (0)