-
-
Notifications
You must be signed in to change notification settings - Fork 18.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PERF: Faster transposition of frames with masked arrays #52836
PERF: Faster transposition of frames with masked arrays #52836
Conversation
@topper-123 have you seen #52083 and #52689? |
Using the timings in the OP, I'm seeing
I haven't yet looked into the implementation to see where this difference is coming from. I'm happy to go with this implementation, would like to see if we can get this in 2.0.2. |
I've merged the latest changes to the main branch into this in case this is he one we go with. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, cc @jorisvandenbossche @jbrockmendel
pandas/core/arrays/masked.py
Outdated
@@ -1414,3 +1414,32 @@ def _groupby_op( | |||
# res_values should already have the correct dtype, we just need to | |||
# wrap in a MaskedArray | |||
return self._maybe_mask_result(res_values, result_mask) | |||
|
|||
|
|||
def transpose_homogenous_masked_arrays(masked_arrays): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
annotation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
pandas/core/arrays/masked.py
Outdated
transposed_values = np.empty(transposed_shape, dtype=values[0].dtype) | ||
for i, val in enumerate(values): | ||
transposed_values[i, :] = val | ||
transposed_values = transposed_values.copy(order="F") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is faster than np.concatenate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's about the same. I'll change to use np.concatenate, it's fewer lines.
pandas/core/frame.py
Outdated
if isinstance(self._mgr, ArrayManager): | ||
masked_arrays = self._mgr.arrays | ||
else: | ||
masked_arrays = [blk.values for blk in self._mgr.blocks] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be safer to use iter_column_arrays? this might mess up if blocks get shuffled in a weird order
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed it.
0a878f4
to
f36143c
Compare
ping... |
@topper-123 - have a conflict. @jbrockmendel - friendly ping. |
* Improve performance when selecting rows and columns * Update doc/source/whatsnew/v2.1.0.rst Co-authored-by: Matthew Roeschke <[email protected]> * Update indexing.py * Update v2.1.0.rst --------- Co-authored-by: Matthew Roeschke <[email protected]>
…3088) * PERF: Improve performance when accessing GroupBy.groups * Update v2.1.0.rst * Fix
* Improve performance when selecting rows and columns * Update doc/source/whatsnew/v2.1.0.rst Co-authored-by: Matthew Roeschke <[email protected]> * Update indexing.py * Update v2.1.0.rst --------- Co-authored-by: Matthew Roeschke <[email protected]>
…3088) * PERF: Improve performance when accessing GroupBy.groups * Update v2.1.0.rst * Fix
7188f20
to
1852bb2
Compare
Ping. |
This pull request is stale because it has been open for thirty days with no activity. Please update and respond to this comment if you're still interested in working on this. |
The PR has gone quite stale, I think it's best to close this PR, unless it can be approved for merging. cc @jbrockmendel , @rhshadrach . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm; two minor requests and a conflict and I think we're good here.
I've updated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Thanks @topper-123 |
Thanks. In total, after the other related PRs have been merged, we have: n [1]: import pandas as pd, numpy as np
...: values = np.random.randn(100000, 4)
...: values = values.astype(int)
...: df = pd.DataFrame(values).astype("Int64")
>>> %timeit df.transpose()
1.91 s ± 3.08 ms per loop # main at start
563 ms ± 2.48 ms per loop # this PR, originally
375 ms ± 5.47 ms per loop # this PR, now An improvement, but very slow still... |
Faster transpose of dataframes with homogenous masked arrays. This also helps when doing reductions with
axis=1
as those currently transpose data before doing reductions.Performance example:
Running
asv continuous -f 1.1 upstream/main HEAD -b reshape.ReshapeMaskedArrayDtype.time_transpose
:There may be possible to improve performance when frames have a common masked dtype, I intend to look into that in a followup.