Сортировка многомерного массива NumPy - PullRequest
0 голосов
/ 18 апреля 2019

Я бы хотел отсортировать массив 2x2 по координатам x. Моя цель - получить массив, отсортированный от наименьшего значения X к наибольшему в каждой паре точек, и в то же время, используя все значения массива

Массив был создан с использованием этой строки кода:

rect = np.empty((4, 2, 2))

Фактический вывод значения внутри массива:

[[[ -1000 , 97 ] #x0,y0 rect 0
   [999 , 98]]   #x1,y1 rect 0
  [[410 , -1048] #x0,y0 rect 1
   [619 , 940]]  #x1,y1 rect 1
  [[-1000, 226] 
   [999 , 227]]
  [[229 , -983]
   [55 , 1008]]]

Желаемым результатом является сортировка по наименьшему значению X внутри каждой пары точек, образующих прямоугольник, а затем сортировка по X с учетом всех прямоугольников следующим образом:

 [[[ -1000 , 97 ] 
   [999 , 98]] 
  [[-1000, 226] 
   [999 , 227]]
  [[55 , 1008]
   [229 , -983]]
  [[410 , -1048] 
   [619 , 940]]]

Ответы [ 3 ]

1 голос
/ 18 апреля 2019

Если вы хотите сделать это без создания дополнительных копий массива, вы можете сделать это, используя комбинацию argsort и индексирование.

import numpy as np
data = np.array(
 [[[ -1000 , 97 ],
   [999 , 98]],
  [[410 , -1048],
   [619 , 940]],
  [[-1000, 226] ,
   [999 , 227]],
  [[229 , -983],
   [55 , 1008]]])
def sortrect(rect):
    x = rect[:, 0]
    idx = np.argsort(x)
    rect[:] = rect[idx]

for a in data:
    sortrect(a)

minx = data[:, 0, 0]
idx = np.argsort(minx)
data[:] = data[idx]

То же самое, без циклов, номенее педагогический (спасибо Мартину за argsort с осью):

idx0 = np.arange(data.shape[0])[:, np.newaxis]
idx1 = np.argsort(data[:, :, 0], axis=1)
data = data[idx0, idx1]

minx = data[:, 0, 0]
idx = np.argsort(minx)
data[:] = data[idx]

Выражение формы out = data[idx0, idx1] означает

for all i, j:
    out[i, j] = data[idx0[i, j], idx1[i, j]].

См. https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#integer-array-indexing для получения более подробной информации.

1 голос
/ 18 апреля 2019

Прощай, петли и лямбды, приветственная скорость

import numpy as np 

original_array = np.array([[[ -1000 , 97 ],[999 , 98]],
               [[410 , -1048],[619 , 940]],  #original_array1,y1 rect 1
                [[-1000, 226],[999 , 227]],
                [[229 , -983],[55 , 1008]]])

#get indices of sorted x0 and x1 (0 means first element of both arrays)
# indices are 2 arrays - [0,0,0,1], [1,1,1,0],
# so you can see that last element needs to reposition
indices = np.argsort(original_array[:,:,0],axis=1)

#create new array
new = np.empty(shape=[4,2,2])

#move on correct posisitions sub arrays
#np.arange only create artifical indices for each rect
new[:,0,:]=original_array[np.arange(original_array.shape[0]),indices[:,0],:]
new[:,1,:]=original_array[np.arange(original_array.shape[0]),indices[:,1],:]

#When subarrays are sorted, sort parent arrays
final_sorted_array = new[new[:,0,0].argsort(),:,:]
print(final_sorted_array)



 [[[-1000.    97.]
  [  999.    98.]]

 [[-1000.   226.]
  [  999.   227.]]

 [[   55.  1008.]
  [  229.  -983.]]

 [[  410. -1048.]
  [  619.   940.]]]
0 голосов
/ 18 апреля 2019

Для этого можно использовать параметр key функции сортировки:

l = [[[ -1000 , 97 ],[999 , 98]],
     [[410 , -1048], [619 , 940]],
     [[-1000, 226],[999 , 227]],
     [[229 , -983],[55 , 1008]]]
sorted(l, key=lambda x: (min(x[0][0], x[1][0]), max(x[0][0],x[1][0])))
>>> [[[-1000, 97],  [999, 98]],
     [[-1000, 226], [999, 227]],
     [[229, -983],  [55, 1008]],
     [[410, -1048], [619, 940]]]

Лямбда внутри отсортированного создает кортеж, содержащий минимальное и максимальное значение x

И если вы работаете с Numpy, вы можете написать что-то, что лучше обобщать в более высоких измерениях:

sorted(l, key=lambda x: sorted(x[..., 0]))
>>> [array([[-1000,    97], [  999,    98]]), 
    array([[-1000,   226], [  999,   227]]), 
    array([[ 229, -983], [  55, 1008]]), 
    array([[  410, -1048], [  619,   940]])]

Это работает, даже если у вас есть более 2 точек для определения вашей формы и будет сортировать по минимальному x значению

EDIT: Исправление для сортировки внутренних точек внутри прямоугольника:

sorted(np.sort(l, axis=1), key=lambda x: tuple(x[..., 0]))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...