我有一个矩阵:
A = [ [1,2],
[3,4],
[5,6] ]
还有一个值的向量:
V = [4,6,2]
我希望能够使用V的值按照第2列重新排序A。结果应该如下所示:
A = [ [3,4],
[5,6],
[1,2] ] # 2nd columns' values have the same order as V
如何做到呢?
A
第二列中的值的索引,以便匹配V
的顺序。在这种情况下,它是[1,2,0]
。一旦我们有了这些,我们就可以使用numpy的“fancy”索引来完成剩下的工作。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列表,则可以像下面显示的那样做。这是一个hack,可能有更好的方法,但是...
我们可以利用numpy.unique
来实现这一点... 我在这里做的是依靠特定的实现细节(unique
似乎从数组末尾开始),这个细节随时都可能发生变化... 这就是它变成了一个丑陋的hack的原因。
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,:]
@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)
如果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]
然后我们使用Joe的解决方案:
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:]
在使用v_order
重新排序之前,通过形成A[np.argsort(a_order)]
来对A
进行排序:
print A[np.argsort(a_order)][v_order]
[[104 105]
[108 109]
[106 107]
[100 101]
[102 103]]
(A[np.argsort(a_order)]
是按照其第二列排序后的A
。)
return_inverse=True
时返回的索引是重构原始数组的唯一数组的索引。也就是说,如果像这样调用np.unique
:uniq_arr, indices = np.unique(arr, return_inverse=True)
您有保障
unique_arr[indices] = arr
unique
总是会以这种方式行事。(著名的最后一句话 -- 考虑到np.unique1d
返回的输出参数顺序发生了什么...但不要在意 :))
V
对A
进行排序...(如果你想这样做,只需要使用np.argsort
然后使用索引或其他类似的方法即可。)你想要A
与V
相同的顺序。再说了,可能有比我描述的更简单的方法... - Joe Kington