2014-10-07 3 views
2

Есть несколько вопросов, которые приближаются, но я не нашел конкретного ответа на этот вопрос. Я пытаюсь выполнить некоторую локальную сортировку массивного 3D-массива вдоль заданной оси. Я не хочу простой сортировки, хотя, я хочу прибегнуть к массиву в соответствии с моим собственным индексом. Напримерсортировка массива нумерации на месте по заданному индексу

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

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

new_order = [1,2,0] 

Я бы ожидать, чтобы иметь возможность сказать:

a[:,:,new_order] = a 

, но это не ведет себя так, как ожидалось. Предложения?

+2

Вы ищете 'a = a [:,:, new_order]'? – farenorth

+0

Это было так давно, что я забыл, что вы можете сделать это в Матлабе. – farenorth

ответ

4

np.ndarray.sort - единственный вид, который утверждает, что находится на месте, и он не дает вам большого контроля.

Помещение индекса заказа справа работает, но может дать непредсказуемые результаты. Очевидно, что он выполняет какое-то последовательное назначение, а более раннее назначение слева может влиять на значения справа.

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]]) 

Для выполнения такого рода предсказуемости требуется какая-то буферизация.

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]]) 

Индексация права оборачивается вокруг этого, но это не на месте. Переменная a указывает на новый объект.

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]]) 

Однако назначение с [:] может решить эту проблему:

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]]) 

Тот факт, что идентификатор a.data одно и то же указывает на то, что это действие Inplace. Но было бы неплохо проверить это с помощью других индексирования, чтобы убедиться, что он делает то, что вы хотите.

Но, нужна ли «на месте» сортировка? Если массив очень велик, он может понадобиться, чтобы избежать ошибок памяти. Но нам нужно будет проверить альтернативы, чтобы увидеть, работают ли они.

inplace имеет значение, если имеется и другая переменная, использующая одни и те же данные. Например

b = a.T # a transpose 

С a[:]= будет заказана строка b. a и b продолжают делиться теми же data. С a=, b не изменилось. a и b теперь развязаны.

0

Вот,

a = a[:, :, new_order] 

Кроме того, здесь есть пара 'NumPy для пользователей MatLab' страниц, которые я нашел полезным, когда я начала работы:

http://wiki.scipy.org/NumPy_for_Matlab_Users

http://mathesaurus.sourceforge.net/matlab-numpy.html

+1

Но это не «на месте». 'b = a [:,:, new_order]' делает то же самое, за исключением того, что старый массив 'a' не является бесплатным для сбора мусора. – hpaulj

Смежные вопросы