撤销或反转argsort(),python

39 投票
7 回答
16798 浏览
提问于 2025-04-15 20:38

给定一个数组'a',我想按列对这个数组进行排序,使用sort(a, axis=0)。然后对数组做一些处理,最后再把排序的结果撤销。这里的撤销不是重新排序,而是基本上要把每个元素的移动方式反过来。我想argsort()是我需要的,但我不太清楚如何用argsort()的结果来排序数组,或者更重要的是,如何应用argsort()的反向操作。

这里有更多的细节

我有一个数组ashape(a) = rXc,我需要对每一列进行排序。

aargsort = a.argsort(axis=0)  # May use this later
aSort = a.sort(axis=0)

然后计算每一行的平均值。

aSortRM = asort.mean(axis=1)

接着用每行的平均值替换该行中的每一列。有没有比这个更好的方法呢?

aWithMeans = ones_like(a)
for ind in range(r)  # r = number of rows
    aWithMeans[ind]* aSortRM[ind]

现在我需要撤销第一步中做的排序。????

7 个回答

12

对于那些仍在寻找答案的人:

In [135]: r = rand(10)

In [136]: i = argsort(r)

In [137]: r_sorted = r[i]

In [138]: i_rev = zeros(10, dtype=int)

In [139]: i_rev[i] = arange(10)

In [140]: allclose(r, r_sorted[i_rev])

Out[140]: True
83

你可能有更好的方法来解决你真正想解决的问题,而不是这个(通常执行 argsort 的时候其实不需要真的去排序),不过我还是给你提供这个:

>>> import numpy as np
>>> a = np.random.randint(0,10,10)
>>> aa = np.argsort(a)
>>> aaa = np.argsort(aa)
>>> a # original
array([6, 4, 4, 6, 2, 5, 4, 0, 7, 4])
>>> a[aa] # sorted
array([0, 2, 4, 4, 4, 4, 5, 6, 6, 7])
>>> a[aa][aaa] # undone
array([6, 4, 4, 6, 2, 5, 4, 0, 7, 4])
9

我不太确定在 numpy 中怎么做最好,但在纯 Python 中,思路是这样的:

aargsort 里保存的是一个排列,表示 aSort 中的元素最初来自哪里——就像在纯 Python 中:

>>> x = list('ciaobelu')
>>> r = range(len(x))
>>> r.sort(key=x.__getitem__)
>>> r
[2, 4, 0, 5, 1, 6, 3, 7]
>>> 

也就是说,sorted(x) 的第一个参数会是 x[2],第二个是 x[4],依此类推。

所以,给定排序后的版本,你可以通过“把元素放回它们原来的地方”来重建原始数据:

>>> s = sorted(x)
>>> s
['a', 'b', 'c', 'e', 'i', 'l', 'o', 'u']
>>> original = [None] * len(s)
>>> for i, c in zip(r, s): original[i] = c
... 
>>> original
['c', 'i', 'a', 'o', 'b', 'e', 'l', 'u']
>>> 

当然,在 numpy 中会有更紧凑和更快的方法来表达这个过程(不过我对它的了解没有对 Python 本身那么深入;-),但我希望这能通过展示“把东西放回原位”的基本逻辑来帮助你理解你需要执行的操作。

撰写回答