numpy:按指定值重新排序数组

Jak*_* M. 5 python numpy

我有一个矩阵:

A = [ [1,2],
      [3,4],
      [5,6] ]
Run Code Online (Sandbox Code Playgroud)

和一个值向量:

V = [4,6,2]
Run Code Online (Sandbox Code Playgroud)

我想使用V中的值重新排序A到第2列.结果应该是:

A = [ [3,4],
      [5,6], 
      [1,2] ] # 2nd columns' values have the same order as V
Run Code Online (Sandbox Code Playgroud)

怎么做?

Joe*_*ton 7

首先,我们需要在第二列中找到值的指标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,:]
Run Code Online (Sandbox Code Playgroud)

如果你想完全避免python列表,那么你可以做如下所示的事情.它是hackish,可能有更好的方式,但......

我们可以滥用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,:]
Run Code Online (Sandbox Code Playgroud)


unu*_*tbu 6

@ JoeKington的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)
Run Code Online (Sandbox Code Playgroud)

如果A看起来像这样:

[[104 105]
 [102 103]
 [108 109]
 [100 101]
 [106 107]]
Run Code Online (Sandbox Code Playgroud)

V

V = A[:,1].copy()
np.random.shuffle(V)
print(V)
Run Code Online (Sandbox Code Playgroud)

看起来像这样:

[105 109 107 101 103]
Run Code Online (Sandbox Code Playgroud)

然后我们使用Joe的解决方案:

vals, order = np.unique(np.hstack((A[:,1],V)), return_inverse=True)
Run Code Online (Sandbox Code Playgroud)

但节省双方的顺序A[:,1]V:

a_order = order[:V.size]
v_order = order[-V.size:]
Run Code Online (Sandbox Code Playgroud)

在重新排序之前进行排序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]]
Run Code Online (Sandbox Code Playgroud)

(A[np.argsort(a_order)]A按照其第二列进行排序).


请注意,np.unique始终按排序顺序返回数组.文档保证return_inverse=True返回的索引是重建原始数组的唯一数组的索引.也就是说,如果你这样打电话np.unique:

uniq_arr, indices = np.unique(arr, return_inverse=True)
Run Code Online (Sandbox Code Playgroud)

你保证

unique_arr[indices] = arr
Run Code Online (Sandbox Code Playgroud)

因为你可以依赖这种关系,所以Joe的方法并不仅仅依赖于一个实现细节 - unique总会以这种方式运行.(着名的最后一句话 - 考虑到由... 返回的输出参数顺序发生了什么np.unique1d......但不要介意:))