Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

in-place numpy array sorting according to given index

Tags:

python

numpy

There are some questions that come close, but I haven't found a specific answer to this. I'm trying to do some in-place sorting of a numpy 3D array along a given axis. I don't want simple sorting though, I want to resort the array according to my own index. For example

a = np.random.rand((3,3,3))

and let's say I want to resort the last dimension according to the following indices of the old array:

new_order = [1,2,0]

I would expect to be able to say:

a[:,:,new_order] = a

but this does not behave as expected. Suggestions?

like image 342
James Avatar asked Oct 16 '25 17:10

James


1 Answers

np.ndarray.sort is the only sort that claims to be inplace, and it does not give you much control.

Placing the order index on the right works - but can give unpredictable results. Evidently it is doing some sort of sequential assignment, and an earlier assignment on the left can affect values on the right.

In [719]: a=np.arange(12).reshape(3,4)
In [720]: a[:,[0,1,3,2]]=a
In [721]: a
Out[721]: 
array([[ 0,  1,  2,  2],
       [ 4,  5,  6,  6],
       [ 8,  9, 10, 10]])

To do this sort of assignment predictably requires some sort of buffering.

In [728]: a[:,[0,1,3,2]]=a.copy()
In [729]: a
Out[729]: 
array([[ 0,  1,  3,  2],
       [ 4,  5,  7,  6],
       [ 8,  9, 11, 10]])

Indexing of the right gets around this, but this is not in-place. The variable a points to a new object.

In [731]: a=a[:,[0,1,3,2]]
In [732]: a
Out[732]: 
array([[ 0,  1,  3,  2],
       [ 4,  5,  7,  6],
       [ 8,  9, 11, 10]])

However assignment with [:] may solve this:

In [738]: a=np.arange(12).reshape(3,4)
In [739]: a.__array_interface__
Out[739]: 
{'data': (181868592, False),   # 181... is the id of the data buffer
 'descr': [('', '<i4')],
 'shape': (3, 4),
 'strides': None,
 'typestr': '<i4',
 'version': 3}
In [740]: a[:]=a[:,[0,1,3,2]]
In [741]: a.__array_interface__
Out[741]: 
{'data': (181868592, False),  # same data buffer
 'descr': [('', '<i4')],
 'shape': (3, 4),
 'strides': None,
 'typestr': '<i4',
 'version': 3}
In [742]: a
Out[742]: 
array([[ 0,  1,  3,  2],
       [ 4,  5,  7,  6],
       [ 8,  9, 11, 10]])

The fact that the a.data id is the same indicates that this is an inplace action. But it would be good to test this with other indexing to make sure it does what you want.

But, is 'inplace' sorting necessary? If the array is very large it might be needed to avoid memory errors. But we'd have to test the alternatives to see if they work.

inplace matters also if there is some other variable that uses the same data. For example

b = a.T # a transpose

With a[:]= the rows of b will be reordered. a and b continue to share the same data. With a=, b is unchanged. a and b are now decoupled.

like image 149
hpaulj Avatar answered Oct 18 '25 08:10

hpaulj



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!