0

Say I have a length n*m array:

x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8]) #take n = m = 3

I want an operation equivalent to

x = x.reshape(n, m).T.flatten()

Which produces the following output:

x = np.array([0, 3, 6, 1, 4, 7, 2, 5, 8])

However, I suspect there is a more efficient way than "reshape, then transpose, then flatten". Is there a witty one-liner? Thanks

Xanshiz
  • 95
  • 1
  • 6
  • Is this a snippet from a wider program? `flatten` could be a bottleneck in some situations since it returns a copy, but the `reshape` and `T` operations should be pretty fast since they're returning views (e.g. see [here](https://stackoverflow.com/questions/22053050/difference-between-numpy-array-shape-r-1-and-r)). – Alexander L. Hayes Dec 09 '22 at 18:27
  • `x = x.reshape(n, m).T.flatten()` is a one liner ... and as numpy uses views it has no performance loss, as only `flatten` will make a copy. – Ahmed AEK Dec 09 '22 at 18:27

1 Answers1

0
In [327]: x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
In [329]: x.reshape(3,3)
Out[329]: 
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

In [330]: x.reshape(3,3).base
Out[330]: array([0, 1, 2, 3, 4, 5, 6, 7, 8])

In [331]: x.reshape(3,3).T.base
Out[331]: array([0, 1, 2, 3, 4, 5, 6, 7, 8])

The reshape and transpose return view, so are relatively fast. It's the reshape after the transpose that makes a copy.

We can specify an order when reshaping:

In [332]: x.reshape(3,3,order='F')
Out[332]: 
array([[0, 3, 6],
       [1, 4, 7],
       [2, 5, 8]])

But again the reshape after makes a copy:

In [333]: x.reshape(3,3,order='F').ravel()
Out[333]: array([0, 3, 6, 1, 4, 7, 2, 5, 8])

Actually if we specify the same order, the ravel is a view:

In [334]: x.reshape(3,3,order='F').ravel(order='F')
Out[334]: array([0, 1, 2, 3, 4, 5, 6, 7, 8])

But the default order of reshape/ravel is 'C':

In [335]: x.reshape(3,3,order='F').ravel(order='C')
Out[335]: array([0, 3, 6, 1, 4, 7, 2, 5, 8])

Regardless of how we do it, reordering the elements as in [335] requires a copy; it can't be a view.

hpaulj
  • 221,503
  • 14
  • 230
  • 353