按列对NumPy中的数组进行排序

时间:2010-05-13 15:32:58

标签: python arrays sorting numpy scipy

如何在第n列中对NumPy中的数组进行排序?

例如,

a = array([[9, 2, 3],
           [4, 5, 6],
           [7, 0, 5]])

我想按第二列对行进行排序,以便我回来:

array([[7, 0, 5],
       [9, 2, 3],
       [4, 5, 6]])

15 个答案:

答案 0 :(得分:587)

我认为这有效:a[a[:,1].argsort()]

这表示a的第二列,并根据它进行排序。

答案 1 :(得分:115)

@steve实际上是最优雅的做法。

对于“正确”方式,请参阅numpy.ndarray.sort

的order关键字参数

但是,您需要将数组视为带有字段(结构化数组)的数组。

如果您最初没有使用字段定义数组,那么“正确”方式会非常难看......

作为一个简单的例子,要对它进行排序并返回副本:

In [1]: import numpy as np

In [2]: a = np.array([[1,2,3],[4,5,6],[0,0,1]])

In [3]: np.sort(a.view('i8,i8,i8'), order=['f1'], axis=0).view(np.int)
Out[3]: 
array([[0, 0, 1],
       [1, 2, 3],
       [4, 5, 6]])

要就地排序:

In [6]: a.view('i8,i8,i8').sort(order=['f1'], axis=0) #<-- returns None

In [7]: a
Out[7]: 
array([[0, 0, 1],
       [1, 2, 3],
       [4, 5, 6]])

@ Steve真的是最优雅的方式,据我所知......

此方法的唯一优势是“order”参数是按顺序排序的字段列表。例如,您可以按第二列排序,然后按第三列排序,然后按顺序排序第一列= ['f1','f2','f0']。

答案 2 :(得分:23)

您可以按照Steve Tjoa的方法对多个列进行排序,方法是使用类似mergesort的稳定排序,并将索引从最不重要的列排序到最重要的列:

a = a[a[:,2].argsort()] # First sort doesn't need to be stable.
a = a[a[:,1].argsort(kind='mergesort')]
a = a[a[:,0].argsort(kind='mergesort')]

按列0排序,然后是1,然后是2。

答案 3 :(得分:19)

来自the Python documentation wiki,我认为你可以这样做:

a = ([[1, 2, 3], [4, 5, 6], [0, 0, 1]]); 
a = sorted(a, key=lambda a_entry: a_entry[1]) 
print a

输出结果为:

[[[0, 0, 1], [1, 2, 3], [4, 5, 6]]]

答案 4 :(得分:16)

如果有人想在其程序的关键部分使用排序,请对不同的提案进行性能比较:

import numpy as np
table = np.random.rand(5000, 10)

%timeit table.view('f8,f8,f8,f8,f8,f8,f8,f8,f8,f8').sort(order=['f9'], axis=0)
1000 loops, best of 3: 1.88 ms per loop

%timeit table[table[:,9].argsort()]
10000 loops, best of 3: 180 µs per loop

import pandas as pd
df = pd.DataFrame(table)
%timeit df.sort_values(9, ascending=True)
1000 loops, best of 3: 400 µs per loop

因此,看起来使用argsort进行索引是迄今为止最快的方法......

答案 5 :(得分:14)

the NumPy mailing list开始,这是另一种解决方案:

>>> a
array([[1, 2],
       [0, 0],
       [1, 0],
       [0, 2],
       [2, 1],
       [1, 0],
       [1, 0],
       [0, 0],
       [1, 0],
      [2, 2]])
>>> a[np.lexsort(np.fliplr(a).T)]
array([[0, 0],
       [0, 0],
       [0, 2],
       [1, 0],
       [1, 0],
       [1, 0],
       [1, 0],
       [1, 2],
       [2, 1],
       [2, 2]])

答案 6 :(得分:3)

我遇到了类似的问题。

我的问题:

我想计算一个SVD,需要按降序排序eigenvalues。但我想保持特征值和特征向量之间的映射。 我的特征值在第一行,而在它下面的相应特征向量在同一列中。

所以我想按第一行按降序排列一个二维数组。

我的解决方案

a = a[::, a[0,].argsort()[::-1]]

那么这是如何运作的?

a[0,]只是我要排序的第一行。

现在我使用argsort来获取索引的顺序。

我使用[::-1]因为我需要降序。

最后,我使用a[::, ...]以正确的顺序获取列的视图。

答案 7 :(得分:3)

import numpy as np
a=np.array([[21,20,19,18,17],[16,15,14,13,12],[11,10,9,8,7],[6,5,4,3,2]])
y=np.argsort(a[:,2],kind='mergesort')# a[:,2]=[19,14,9,4]
a=a[y]
print(a)

所需的输出为[[6,5,4,3,2],[11,10,9,8,7],[16,15,14,13,12],[21,20,19,18,17]]

请注意,argsort(numArray)返回numArray的索引,因为它应该以排序的方式排列。

示例

x=np.array([8,1,5]) 
z=np.argsort(x) #[1,3,0] are the **indices of the predicted sorted array**
print(x[z]) #boolean indexing which sorts the array on basis of indices saved in z

答案应为[1,5,8]

答案 8 :(得分:1)

稍微复杂一点的.T示例 - 在第1列上下降,在第2列上下降。 In [120]: b=np.array([[1,2,1],[3,1,2],[1,1,3],[2,3,4],[3,2,5],[2,1,6]]) In [121]: b Out[121]: array([[1, 2, 1], [3, 1, 2], [1, 1, 3], [2, 3, 4], [3, 2, 5], [2, 1, 6]]) In [122]: b[np.lexsort(([1,-1]*b[:,[1,0]]).T)] Out[122]: array([[3, 1, 2], [3, 2, 5], [2, 1, 6], [2, 3, 4], [1, 1, 3], [1, 2, 1]]) 的技巧是对行进行排序(因此为addChildViewController(controller) controller.view.frame = ... view.addSubview(controller.view) controller.didMoveToParentViewController(self) ),并优先考虑最后一行。

{{1}}

答案 9 :(得分:0)

这是考虑所有列的另一种解决方案(J.J答案的更紧凑方式);

ar=np.array([[0, 0, 0, 1],
             [1, 0, 1, 0],
             [0, 1, 0, 0],
             [1, 0, 0, 1],
             [0, 0, 1, 0],
             [1, 1, 0, 0]])

用lexsort排序,

ar[np.lexsort(([ar[:, i] for i in range(ar.shape[1]-1, -1, -1)]))]

输出:

array([[0, 0, 0, 1],
       [0, 0, 1, 0],
       [0, 1, 0, 0],
       [1, 0, 0, 1],
       [1, 0, 1, 0],
       [1, 1, 0, 0]])

答案 10 :(得分:0)

只需使用排序,请使用要排序的列号。

a = np.array([1,1], [1,-1], [-1,1], [-1,-1]])
print (a)
a=a.tolist() 
a = np.array(sorted(a, key=lambda a_entry: a_entry[0]))
print (a)

答案 11 :(得分:0)

这是一个古老的问题,但是如果您需要将其推广到2维以上的数组,则可以采用以下解决方案:

np.einsum('ij->ij', a[a[:,1].argsort(),:])

这对于二维来说是一个过大的杀伤力,对于每个@steve的答案,a[a[:,1].argsort()]就足够了,但是不能将答案推广到更高的维度。您可以找到an example of 3D array in this question.

输出:

[[7 0 5]
 [9 2 3]
 [4 5 6]]

答案 12 :(得分:0)

#用于沿第1列排序

indexofsort=np.argsort(dataset[:,0],axis=-1,kind='stable') 
dataset   = dataset[indexofsort,:]

答案 13 :(得分:0)

def sort_np_array(x, column=None, flip=False):
    x = x[np.argsort(x[:, column])]
    if flip:
        x = np.flip(x, axis=0)
    return x

原始问题中的数组:

a = np.array([[9, 2, 3],
              [4, 5, 6],
              [7, 0, 5]])

问题作者所预期的 sort_np_array 函数的结果:

sort_np_array(a, column=1, flip=False)
[2]: array([[7, 0, 5],
            [9, 2, 3],
            [4, 5, 6]])

答案 14 :(得分:0)

感谢这篇文章:https://stackoverflow.com/a/5204280/13890678

我使用 structured array 找到了一个更“通用”的答案。 我认为这种方法的一个优点是代码更易于阅读。

import numpy as np
a = np.array([[9, 2, 3],
           [4, 5, 6],
           [7, 0, 5]])

struct_a = np.core.records.fromarrays(
    a.transpose(), names="col1, col2, col3", formats="i8, i8, i8"
)
struct_a.sort(order="col2")

print(struct_a)
[(7, 0, 5) (9, 2, 3) (4, 5, 6)]