我有一个数组,它的形状是。我将按最后一列对该数组进行排序,以便:
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]
和.npy
与r
进行比较,您会发现这不等于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/