numpy: переупорядочить массив по указанным значениям - PullRequest
5 голосов
/ 25 октября 2011

У меня есть матрица:

A = [ [1,2],
      [3,4],
      [5,6] ]

и вектор значений:

V = [4,6,2]

Я хотел бы изменить порядок A на 2-й столбец, используя значения из V. Результат долженбыть:

A = [ [3,4],
      [5,6], 
      [1,2] ] # 2nd columns' values have the same order as V

Как это сделать?

Ответы [ 2 ]

7 голосов
/ 25 октября 2011

Во-первых, нам нужно найти признаки значений во втором столбце A, которые нам должны соответствовать порядку V.В данном случае это [1,2,0].Как только мы получим их, мы можем просто использовать «причудливую» индексацию numpy, чтобы сделать все остальное.

Итак, вы можете сделать что-то вроде этого:

import numpy as np
A = np.arange(6).reshape((3,2)) + 1
V = [4,6,2]
column = A[:,1].tolist()
order = [column.index(item) for item in V]
print A[order,:]

Если вы хотите избежать списков Pythonполностью, тогда вы можете сделать что-то вроде того, что показано ниже.Это хакерский, и может быть лучший способ, хотя ...

Мы можем злоупотребить numpy.unique, чтобы сделать это ... То, что я делаю здесь, зависит от конкретной детали реализации (uniqueкажется, начинается с конца массива), который может измениться в любое время ... Вот что делает его безобразным хаком.

import numpy as np
A = np.arange(6).reshape((3,2)) + 1
V = np.array([4,6,2])
vals, order = np.unique(np.hstack((A[:,1],V)), return_inverse=True)
order = order[-V.size:]
print A[order,:]
6 голосов
/ 26 октября 2011

@ numpy решение ДжоКингтона очень умно, но полагается на A[:,1] в отсортированном порядке. Вот исправление для общего случая:

import numpy as np

np.random.seed(1)
N=5
A = np.arange(2*N).reshape((-1,2))+100
np.random.shuffle(A)
print(A)

Если A выглядит так:

[[104 105]
 [102 103]
 [108 109]
 [100 101]
 [106 107]]

и V

V = A[:,1].copy()
np.random.shuffle(V)
print(V)

выглядит так:

[105 109 107 101 103]

тогда мы используем решение Джо:

vals, order = np.unique(np.hstack((A[:,1],V)), return_inverse=True)

, но сохраните порядок A[:,1] и V:

a_order = order[:V.size]
v_order = order[-V.size:]

и сортировку A (путем формирования A[np.argsort(a_order)]) перед переупорядочением с помощью v_order:

print A[np.argsort(a_order)][v_order]

[[104 105]
 [108 109]
 [106 107]
 [100 101]
 [102 103]]

(A[np.argsort(a_order)] A отсортировано по второму столбцу.)


Обратите внимание, что np.unique всегда возвращает массив в отсортированном порядке. Документация гарантирует с return_inverse=True, что возвращаемые индексы являются индексами уникального массива, который восстанавливает исходный массив. То есть, если вы позвоните np.unique так:

uniq_arr, indices = np.unique(arr, return_inverse=True)

вам гарантировано, что

unique_arr[indices] = arr

Поскольку вы можете положиться на эти отношения, метод Джо не зависит от простой детали реализации - unique всегда будет вести себя таким образом. (Известные последние слова - учитывая то, что случилось с порядком выходных аргументов , возвращаемым np.unique1d ... но не берите в голову:))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...