首页 文章

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

提问于
浏览
227

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

例如,

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

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

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

9 回答

  • 93

    我有类似的问题 .

    My Problem:

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

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

    My Solution

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

    那怎么办?

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

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

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

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

  • 13

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

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

    对于"correct"方式,请参阅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']排序第一列 .

  • 0

    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]]]
    
  • 515

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

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

  • 17

    您可以按照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 .

  • 13

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

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

  • 3

    稍微复杂一点 lexsort 例子 - 在第1列下降,在第2列上次要上升 . 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]])
    
  • 1

    这是考虑 all 列的另一种解决方案(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]])
    

相关问题