REGR/PERF: Fix perf regression in _LocationIndexer._post_expansion_casting#64388
REGR/PERF: Fix perf regression in _LocationIndexer._post_expansion_casting#64388rhshadrach wants to merge 2 commits intopandas-dev:mainfrom
Conversation
pandas/core/indexing.py
Outdated
| orig_obj.iloc[:, i].array, self.obj.iloc[:, i]._values | ||
| ) | ||
| self.obj.isetitem(i, new_arr) | ||
| mask = (self.obj.dtypes != orig_obj.dtypes).reset_index(drop=True) |
There was a problem hiding this comment.
i dont understand why the reset_index. why not ._values?
There was a problem hiding this comment.
and an enumerate instead of .items() in the next line
There was a problem hiding this comment.
ok i guess they're equivalent. never mind.
There was a problem hiding this comment.
Yea, lots of different cases will have one being more performant than the other.
def setup(size, prob):
return pd.Series(random.choices([True, False], [prob, 1.0 - prob], k=size))
def foo():
mask = ser.reset_index(drop=True)
for i, value in mask[mask].items():
pass
def bar():
for i, value in enumerate(ser.tolist()):
if value:
pass
ser = setup(size=10000, prob=0.01)
%timeit foo()
# 130 μs ± 243 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit bar()
# 291 μs ± 9.07 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
ser = setup(size=100, prob=0.01)
%timeit foo()
# 97.1 μs ± 78.8 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit bar()
# 2.75 μs ± 16.8 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)Happy to go either way here.
There was a problem hiding this comment.
Any way we could leverage the self.obj._mgr.get_dtypes() with the self.obj._mgr.blknos to more quickly deduce which columns locations have different dtypes now?
There was a problem hiding this comment.
modest prerence for ._values and enumerate since i find it more immediately obvious what it is doing, but not gonna harp on it.
There was a problem hiding this comment.
Updated, these shaved off another 50ms.
| for i, changed_dtype in enumerate(changed_dtypes): | ||
| if changed_dtype: |
There was a problem hiding this comment.
You can use for i in np.flatnonzero(changed_dtypes) to find the indices where the value is True as well
Ref: #62523
Ref: pandas-dev/asv-runner#104
Details
Still a large regression after this (~25ms -> 120ms), but at a glance doesn't seem easy to clawback the rest.
cc @jbrockmendel