如何按第n列对NumPy中的数组排序?
例如,
a = array([[9, 2, 3],
[4, 5, 6],
[7, 0, 5]])
我想按第二列对行进行排序,以便返回:
array([[7, 0, 5],
[9, 2, 3],
[4, 5, 6]])
如何按第n列对NumPy中的数组排序?
例如,
a = array([[9, 2, 3],
[4, 5, 6],
[7, 0, 5]])
我想按第二列对行进行排序,以便返回:
array([[7, 0, 5],
[9, 2, 3],
[4, 5, 6]])
Answers:
对于“正确”的方式,请参见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”参数是用来对搜索进行排序的字段列表。例如,您可以通过提供order = ['f1','f2','f0']来对第二列,第三列,第一列进行排序。
ValueError: new type not compatible with array.
float
什么呢?我应该改变什么吗?
a = np.array([['a',1,2,3],['b',4,5,6],['c',0,0,1]])
我应该遵循哪种方法?
np.argsort
它们返回的索引可能会占用相当多的内存,最重要的是,使用数组进行索引也会生成要排序的数组的副本。
我想这可行: a[a[:,1].argsort()]
这表示的第二列,a
并据此对其进行排序。
1
这里是什么?索引排序依据?
[:,1]
表示的第二列a
。
a[a[:,1].argsort()[::-1]]
np.sort
?
ind = np.argsort( a[:,1] ); a = a[ind]
您可以按照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。
我认为您可以从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]]]
如果有人想在他们程序的关键部分使用排序,下面是对不同提案的性能比较:
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进行索引是迄今为止最快的方法...
从该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]])
a[np.lexsort(a.T[cols])]
。cols=[1]
原始问题在哪里。
稍微复杂一点的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]])
这是考虑所有列的另一种解决方案(JJ的答案的更紧凑方式);
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]])
np.sort(a, axis=0)
对于给定的矩阵,这将是令人满意的解决方案。我建议使用一个更好的示例进行编辑,但被拒绝了,尽管实际上这个问题要清楚得多。该示例应该类似于a = numpy.array([[1, 2, 3], [6, 5, 2], [3, 1, 1]])
所需的输出array([[3, 1, 1], [1, 2, 3], [6, 5, 2]])