I've got a multidimensional array of shape (1000000,3,2). Essentially it is 1 million sets of samples, each sample being 3 coordinates (each coordinate has an x and y component). I would like to sort each of the samples by the y component of each coordinate. For example, if vecCoords is the full array andI have one of the samples being vecCoords[0,:,:] = [[1,3],[2,1],[4,2]], I want it sorted to give me [[2,1],[4,2],[1,3]]. I was this vectorized so it is done for each of the 1 million samples. So, the output shape is still (1000000,3,2). I tried doing it iteratively, but my code isn't giving me the correct results there, and it is also slower than I would like.
1 Answer
Make a small sample array:
In [153]: arr = np.random.randint(0,100,(4,3,2))
In [154]: arr
Out[154]:
array([[[21, 12],
[15, 31],
[17, 88]],
[[35, 81],
[99, 58],
[39, 46]],
[[54, 54],
[85, 71],
[ 9, 19]],
[[25, 46],
[62, 61],
[74, 69]]])
The values you want to sort:
In [155]: arr[:,:,1]
Out[155]:
array([[12, 31, 88],
[81, 58, 46],
[54, 71, 19],
[46, 61, 69]])
In [156]: idx=np.argsort(arr[:,:,1], axis=1)
In [157]: idx
Out[157]:
array([[0, 1, 2],
[2, 1, 0],
[2, 0, 1],
[0, 1, 2]])
Test this sort on one plane:
In [159]: arr[1,idx[1],:]
Out[159]:
array([[39, 46],
[99, 58],
[35, 81]])
Apply it to all planes:
In [161]: arr[np.arange(arr.shape[0])[:,None], idx,:]
Out[161]:
array([[[21, 12],
[15, 31],
[17, 88]],
[[39, 46],
[99, 58],
[35, 81]],
[[ 9, 19],
[54, 54],
[85, 71]],
[[25, 46],
[62, 61],
[74, 69]]])
While I had a general idea where I was heading with this, I still had to experiment a bit.
A newish function is supposed to make this easier - though even here I had to try a couple of things:
In [168]: np.take_along_axis(arr,idx[:,:,None], axis=1)
Out[168]:
array([[[21, 12],
[15, 31],
[17, 88]],
[[39, 46],
[99, 58],
[35, 81]],
[[ 9, 19],
[54, 54],
[85, 71]],
[[25, 46],
[62, 61],
[74, 69]]])
1 Comment
Zonova
Brilliant, thank you for being thorough and explaining each step!