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

时间:2011-10-25 14:55:30

标签: python numpy

我有一个矩阵:

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

和值向量:

V = [4,6,2]

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

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

怎么做?

2 个答案:

答案 0 :(得分: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,:]

如果你想完全避免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,:]

答案 1 :(得分:6)

@JoeKington's numpy solution非常聪明,但它依赖于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:]

并在使用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始终按排序顺序返回数组。 The documentation保证return_inverse=True返回的索引是重构原始数组的唯一数组的索引。也就是说,如果你这样叫np.unique

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

你可以保证

unique_arr[indices] = arr

因为你可以依赖这种关系,所以Joe的方法不依赖于纯粹的实现细节 - unique将始终以这种方式运行。 (着名的最后一句话 - 考虑np.unique1d返回的order of output arguments发生的事情......但不要介意:))