撤消或反向 argsort(),python

Posted

技术标签:

【中文标题】撤消或反向 argsort(),python【英文标题】:undo or reverse argsort(), python 【发布时间】:2011-01-29 20:00:57 【问题描述】:

给定一个数组'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]

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

【问题讨论】:

为什么你不能在任何转换之前复制数组:a.copy() 或使用aSort = numpy.sort(axis=0)(这将返回排序后的副本)?顺便说一句,a.sort() 什么也不返回,因此没有必要分配它的返回值。 @J.F.塞巴斯蒂安,谢谢你是对的,我修好了 【参考方案1】:

对于您实际尝试解决的问题,可能有比这更好的解决方案(执行 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])

【讨论】:

【参考方案2】:

对于所有仍在寻找答案的人:

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

【讨论】:

顺便说一句,zeros(10, dtype=int) 可以替换为zeros_like(i)【参考方案3】:

我不确定在numpy 中如何最好地做到这一点,但是,在纯 Python 中,推理是:

aargsort 持有range(len(a)) 的排列,告诉您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 本身的了解不如从内到外;-),但我希望这有助于通过展示您需要执行的“将东西放回原处”操作的底层逻辑。

【讨论】:

【参考方案4】:

比赛迟到了,但在这里:

import numpy as np
N = 1000 # or any large integer
x = np.random.randn( N )
I = np.argsort( x )
J = np.argsort( I )
print( np.allclose( x[I[J]] , x ) )
>> True

基本上,argsort argsort 因为反向排序的第 n 个元素是 J[n] = k : I[k] = n。即I[J[n]] = n,所以J对I排序。

【讨论】:

这是迄今为止最好的解决方案 这是一个很好的答案,但它与@paul's solution 有何不同? 谢谢德克斯特。一样的。更清晰,更普遍的测试,并实际解释,而不是仅仅给出。我显然有偏见。但和@paul 一样。【参考方案5】:

indices=np.argsort(a) 为您提供排序索引,因此 x = a[indices] 是排序后的数组。 y = b[indices] 将数组 b 前推到排序域。 c[indices] = zz 从排序域拉回源域中的 c

例如,

import numpy as np

n = 3
a = np.random.randint(0,10,n) # [1, 5, 2]
b = np.random.randn(n) # [-.1, .5, .2]
c = np.empty_like(a)

# indices that sort a: x=a[indices], x==np.sort(a) is all True
indices = np.argsort(a) # [0,2,1]

# y[i] is the value in b at the index of the i-th smallest value in a
y = b[indices] # [-.1, .2, .5]

# say z[i] is some value related to the i-th smallest entry in a 
z = np.random.randn(n) # [-1.1, 1.2, 1.3]
c[indices] = z # inverted the sorting map, c = [-1.1, 1.3, 1.2] 

【讨论】:

【参考方案6】:

我无法按照您的示例进行操作,但更抽象的问题(即如何对数组进行排序然后反转排序)很简单。

import numpy as NP
# create an 10x6 array to work with
A = NP.random.randint(10, 99, 60).reshape(10, 6)
# for example, sort this array on the second-to-last column, 
# breaking ties using the second column (numpy requires keys in
# "reverse" order for some reason)
keys = (A[:,1], A[:,4])
ndx = NP.lexsort(keys, axis=0)
A_sorted = NP.take(A, ndx, axis=0)

从 A_sorted “重建” A 是微不足道的,因为请记住,您首先使用索引数组 ('ndx') 对数组进行排序。

# ndx array for example above:  array([6, 9, 8, 0, 1, 2, 4, 7, 3, 5])

换句话说,A_sorted 中的第 4 行是原始数组 A 中的第 1 行,等等。

【讨论】:

我实际上想单独对每一列进行排序,我在顶部更正了我的代码,但我需要使用 np.sort(A, axis=0) 所以 inex 将是 np.argsort(x , 轴=0)

以上是关于撤消或反向 argsort(),python的主要内容,如果未能解决你的问题,请参考以下文章

撤消(反向合并)Subversion中的更改/版本

python:argsort,将数组升序或降序,将矩阵每一行升序或降序,返回其索引

python - 将 argsort 与掩码相结合以在移动窗口中获取最接近的值

argsort argmax

argsort()

变量.argsort()的用法