numpy undo或reverse argsort(),python

wlwcrazw  于 2023-04-21  发布在  Python
关注(0)|答案(7)|浏览(136)

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

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

lokaqttq

lokaqttq1#

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

a8jjtwal2#

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

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
qv7cva1a

qv7cva1a3#

我不确定如何在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中会有更紧凑、更快速的方法来表达这一点(不幸的是,我对numpy的了解不如对Python本身的了解那么多;- ),但我希望这通过展示您需要执行的“把东西放回原位”操作的底层逻辑来有所帮助。

56lgkhnf

56lgkhnf4#

虽然游戏很晚了,但在这里:

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排序。

6vl6ewon

6vl6ewon5#

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]
iezvtpos

iezvtpos6#

我没能理解你的例子,但是更抽象的问题--即如何对数组排序,然后反转排序--是很简单的。

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行,依此类推。

cl25kdpy

cl25kdpy7#

获得argsort逆的更快的替代方案,灵感来自Alex Martelli

def get_inv (argsort):
    argsort_inv = np.arange(len(argsort))
    argsort_inv[argsort] = argsort_inv.copy()
    return argsort_inv

对于大于1E4的阵列,我看到性能提高了10倍

相关问题