如何根据argsort取消排序np数组

4

我最初有一个未排序的np数组,其中包含多个数组

test = np.array([['A', 'A', 'B', 'E', 'A'],
       ['B', 'E', 'A', 'E', 'B'],
       ['C', 'D', 'D', 'A', 'C'],
       ['B', 'D', 'A', 'C', 'A'],
       ['B', 'A', 'E', 'A', 'E'],
       ['C', 'D', 'C', 'E', 'D']])

根据第一列来对数组进行排序:

argsortTest = test[:,0].argsort()
test_sorted = test[argsortTest]

  test_sorted:  
[['A' 'A' 'B' 'E' 'A']
 ['B' 'E' 'A' 'E' 'B']
 ['B' 'D' 'A' 'C' 'A']
 ['B' 'A' 'E' 'A' 'E']
 ['C' 'D' 'D' 'A' 'C']
 ['C' 'D' 'C' 'E' 'D']]

我对test_sorted数组进行了一些处理,改变了一些值(第一列保持不变,行数也不变)。最后,我想要检索出原始的二维数组并保留更改后的值。因此,我需要再次根据第一列对其进行“取消排序”。

我目前的解决方案:

argsortTestList = argsortTest.tolist()
rangeX = np.array(xrange(6))
unsort_args = [argsortTestList.index(x) for x in rangeX]
unsorted = test_sorted[unsort_args]

我之所以先进行排序,然后在最后再取消排序,是因为在处理已排序的数组时,性能更好。但是由于所做的更改没有反映到原始数组中,因此我不得不再次取消排序。

然而,“取消排序”的解决方案太慢了(大型数据集:约20万行)

1个回答

6

只需执行

b = np.argsort(argsortTest)
test_sorted[b]

# Output
# array([['A', 'A', 'B', 'E', 'A'],
#        ['B', 'E', 'A', 'E', 'B'],
#        ['C', 'D', 'D', 'A', 'C'],
#        ['B', 'D', 'A', 'C', 'A'],
#        ['B', 'A', 'E', 'A', 'E'],
#        ['C', 'D', 'C', 'E', 'D']], 
#       dtype='|S1')

解释

考虑以下数组

comb = np.column_stack((np.arange(argsortTest.size),argsortTest))
comb

# array([[0, 0],
#        [1, 1],
#        [2, 3],
#        [3, 4],
#        [4, 2],
#        [5, 5]])

左列是test的索引,右列是argsort的结果。这意味着索引0对应0,1对应1,2对应3,以此类推。由于第一列已排序,因此我们可以使用高级索引获取有序数组test [argsortTest]
现在,您想要相反的过程,即从右列到左列,使索引0对应0,4对应3,2对应4等等。为了使高级索引适用于左列,右列现在必须排序。
comb[np.argsort(comb[:,1])]

# array([[0, 0],
#        [1, 1],
#        [4, 2],
#        [2, 3],
#        [3, 4],
#        [5, 5]])

但由于这个左列恰好是comb中右列的argsort,因此我们可以得到以下结果:

test = test_sorted[ np.argsort(argsortTest) ]

我希望这有助于理解以下思路...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接