- 
          
- 
        Couldn't load subscription status. 
- Fork 19.2k
PERF: Faster transposition of frames with masked arrays #52836
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
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
          
        
      | 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, nowAn improvement, but very slow still... | 
Faster transpose of dataframes with homogenous masked arrays. This also helps when doing reductions with
axis=1as 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.