在NumPy中按列排序数组

我如何排序一个NumPy数组的第n列?

例如,给定:

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

我想按第二列对a的行进行排序,以获得:

array([[7, 0, 5],
[9, 2, 3],
[4, 5, 6]])
468357 次浏览

a的第二列排序:

a[a[:, 1].argsort()]

@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]])

据我所知,史蒂夫的方法真的是最优雅的……

该方法的唯一优点是“order”参数是一个字段列表,用于排序搜索。例如,您可以通过order=['f1','f2','f0']按第二列排序,然后是第三列,然后是第一列。

正如Python文档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]]]

来自NumPy邮件列表,这里是另一个解决方案:

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

如果有人想在程序的关键部分使用排序,这里是不同方案的性能比较:

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进行索引似乎是迄今为止最快的方法……

你可以按照Steve Tjoa的方法对多个列进行排序,使用像归并排序这样的稳定排序,并从最不重要的列到最重要的列对索引进行排序:

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

稍微复杂一点的lexsort示例-在第一列上降序,在第二列上二次升序。lexsort的技巧是它对行进行排序(因此是.T),并优先考虑最后一行。

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

我也遇到过类似的问题。

我的问题:

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

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

我的解决方案

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

那么这是如何工作的呢?

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

现在我使用argsort来获取下标的顺序。

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

最后,我使用a[::, ...]来获得一个以正确顺序排列的列的视图。

下面是另一个考虑所有列的解决方案(更紧凑的方式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]])

简单地使用排序,使用您想要排序的列号。

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)

这是一个老问题,但如果你需要将其推广到高于2维的数组,下面是可以很容易推广的解决方案:

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

这对于二维来说是一个过度的处理,根据@steve的回答,a[a[:,1].argsort()]就足够了,然而,这个答案不能推广到更高的维度。你可以找到在这个问题中有一个3D数组的例子。

输出:

[[7 0 5]
[9 2 3]
[4 5 6]]
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]

#用于按列1排序

indexofsort=np.argsort(dataset[:,0],axis=-1,kind='stable')
dataset   = dataset[indexofsort,:]
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]])

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

我找到了一个更“一般”的;使用结构数组回答。 我认为这种方法的一个优点是代码更容易阅读

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

熊猫的方法只是为了完整性:

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


             

a.sort_values(1, ascending=True).to_numpy()
array([[7, 0, 5], # '1' means sort by second column
[9, 2, 3],
[4, 5, 6]])

< a href = " https://stackoverflow.com/users/1825593/prl900 " > prl900 基准测试,与接受的答案比较:

%timeit pandas_df.sort_values(9, ascending=True)
1000 loops, best of 3: 400 µs per loop


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