我如何排序一个NumPy数组的第n列?
例如,给定:
a = array([[9, 2, 3],
[4, 5, 6],
[7, 0, 5]])
我想对a的行按第二列进行排序,得到:
array([[7, 0, 5],
[9, 2, 3],
[4, 5, 6]])
我如何排序一个NumPy数组的第n列?
例如,给定:
a = array([[9, 2, 3],
[4, 5, 6],
[7, 0, 5]])
我想对a的行按第二列进行排序,得到:
array([[7, 0, 5],
[9, 2, 3],
[4, 5, 6]])
当前回答
@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']按第二列排序,然后是第三列,然后是第一列。
其他回答
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]])
如果有人想在程序的关键部分使用排序,这里是不同方案的性能比较:
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进行索引是目前为止最快的方法…
这里是另一个考虑所有列的解决方案(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]])
这是一个老问题,但如果你需要将其推广到高于2维的数组,下面是可以很容易推广的解决方案:
np.einsum('ij->ij', a[a[:,1].argsort(),:])
对于二维来说,这是一个过度的处理,对于@steve的答案,一个[a[:,1].argsort()]就足够了,但是这个答案不能推广到更高的维度。你可以在这个问题中找到一个3D数组的例子。
输出:
[[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]])
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