我有一个数组,它的形状是。我将按最后一列对该数组进行排序,以便:

sortx = numpy.argsort( data[:,-1] )[::-1]
sortedData = data[ sortx, : ]

其中data用于将列从高到低排序,而不是从低到高排序,数据为float64。然后我将这个排序数组保存到(N,6)文件中,如下所示:
numpy.save( 'file.npy', sortedData )

但是,当我再次加载数组并检查数据的排序时,它似乎不正常!只是其中的一部分,不是所有的,这很奇怪。
data_again = numpy.load( 'file.npy' )
order = numpy.argsort( data_again[:,-1] )[::-1]
r = numpy.arange( len(data_again) )

如果您将[::-1].npyr进行比较,您会发现这不等于N。大约2%的顺序不同!
首先,我是否正确理解上述代码?其次,有人能复制这个吗?我在Linux上使用Python2.7.2和Numpy1.6.1。
更新:这种行为甚至直接发生在第一次排序之后和保存之前。所以这和分类本身有关。排序列中有重复值。

最佳答案

如果最后一列有重复的值,我可以重现症状:

import numpy as np
np.random.seed(0)
data = np.random.random((8,2))
data[::2,-1] = data[1::2,-1]
print(data)
# [[ 0.5488135   0.54488318]
#  [ 0.60276338  0.54488318]
#  [ 0.4236548   0.891773  ]
#  [ 0.43758721  0.891773  ]
#  [ 0.96366276  0.52889492]
#  [ 0.79172504  0.52889492]
#  [ 0.56804456  0.0871293 ]
#  [ 0.07103606  0.0871293 ]]
sortx = np.argsort( data[:,-1] )[::-1]
sorted_data = data[ sortx, : ]

order = np.argsort( sorted_data[:,-1] )[::-1]
r = np.arange( len(sorted_data) )
print(order)
# [1 0 3 2 5 4 7 6]
print(r)
# [0 1 2 3 4 5 6 7]
print(np.allclose(order, r))
# False

默认情况下,argsort使用快速排序。快速排序不稳定,因此绑定行的顺序不一定与原始数据的顺序相同。
然而,即使您使用稳定的排序,例如mergesort,当您反转np.argsort的结果时,对于绑定的行,更高的索引将排在第一位。
因此,当您第二次调用np.argsort时,您不会得到order等于r
您可以通过对最后一列进行排序并使用np.arange(len(data),0,-1)作为连接断路器来生成该顺序:
sortx = np.lexsort((np.arange(len(data),0,-1), data[:,-1]))[::-1]
sorted_data = data[ sortx, : ]

order = np.lexsort((np.arange(len(data),0,-1), sorted_data[:,-1]))[::-1]
r = np.arange( len(sorted_data) )
print(order)
# [0 1 2 3 4 5 6 7]
print(r)
# [0 1 2 3 4 5 6 7]
print(np.allclose(order, r))
# True

使用np.arange(len(data),0,-1)将较高的索引放在第一位(对于绑定的行),这样当您对索引进行重新排序时,较低的索引是第一位的。

关于python - numpy 1.6.1 argsort()奇怪的行为?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25686307/

10-11 07:41