如何使argsort结果在相等的值之间随机?

13

假设你有一个numpy向量[0,3,1,1,1],并运行argsort后,你将得到[0,2,3,4,1],但所有的1都是相同的!我想要一种有效的方法来随机打乱相同值的索引。有什么好的想法可以不使用带有两个指数的排序向量上的while循环来完成吗?

numpy.array([0,3,1,1,1]).argsort()
2个回答

14

使用lexsort函数:np.lexsort((b,a))表示首先按a排序,然后按b排序。

>>> a
array([0, 3, 1, 1, 1])
>>> b=np.random.random(a.size)
>>> b
array([ 0.00673736,  0.90089115,  0.31407214,  0.24299867,  0.7223546 ])
>>> np.lexsort((b,a))
array([0, 3, 2, 4, 1])
>>> a.argsort()
array([0, 2, 3, 4, 1])
>>> a[[0, 3, 2, 4, 1]]
array([0, 1, 1, 1, 3])
>>> a[[0, 2, 3, 4, 1]]
array([0, 1, 1, 1, 3])

4
这是一种有点取巧的方法,但如果您的数组仅包含整数,则可以添加随机值并对结果进行argsort排序。np.random.rand会给出[0,1)范围内的结果,因此在这种情况下,您可以确保对于不同元素,顺序仍然保持不变。
>>> import numpy as np
>>> arr = np.array([0,3,1,1,1])
>>> np.argsort(arr + np.random.rand(*arr.shape))
array([0, 4, 3, 2, 1])
>>> np.argsort(arr + np.random.rand(*arr.shape))
array([0, 3, 4, 2, 1])
>>> np.argsort(arr + np.random.rand(*arr.shape))
array([0, 3, 4, 2, 1])
>>> np.argsort(arr + np.random.rand(*arr.shape))
array([0, 2, 3, 4, 1])
>>> np.argsort(arr + np.random.rand(*arr.shape))
array([0, 2, 3, 4, 1])
>>> np.argsort(arr + np.random.rand(*arr.shape))
array([0, 4, 2, 3, 1])

在这里,我们可以看到索引0始终是argsort结果中的第一个,索引1是最后一个,但其余结果是随机排序的。
通常,您可以生成受np.diff(np.sort(arr)).max()限制的随机值,但在某些情况下可能会遇到精度问题。

1
假设向量只包含整数,这不是一个太过于武断的假设吗? - CT Zhu
好的,我不知道。我是根据问题中给出的内容来回答的,并且我的答案已经得到认可。不过你的解决方案很不错。 - YXD

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