代码之家  ›  专栏  ›  技术社区  ›  Physicist

基于某些列重新排列二维数组中的条目

  •  1
  • Physicist  · 技术社区  · 5 年前

    假设我有一个 M x N numpy数组,其中每一行表示一个数据项,第一个 N-1

    重新排列不同行以便按参数排序的最优雅的方法是什么?

    例子:

    # original
    1                        0.1                      20                       0.30000000000000004      0.07819319717404902     
    1                        1                        10                       0.2                      0.07550707294415204      
    2                        0.1                      0                        0                        0.07078663749666488      
    2                        0.1                      0                        0.1                      0.07284943819285646      
    1                        1                        15                       0.4                      0.08047398714777267      
    1                        1                        15                       0.5                      0.0820402298018169      
    1                        1                        15                       0.30000000000000004      0.07819319717406738     
    1                        1                        20                       0                        0.07079655446543297      
    1                        1                        20                       0.1                      0.07286704639139795      
    1                        1                        5                        0.4                       0.086521872154
    
    
    
    # desired:
    1                        0.1                      20                       0.30000000000000004      0.07819319717404902     
    1                        1                        5                        0.4                       0.086521872154
    1                        1                        10                       0.2                      0.07550707294415204      
    1                        1                        15                       0.30000000000000004      0.07819319717406738
    1                        1                        15                       0.4                      0.08047398714777267      
    1                        1                        15                       0.5                      0.0820402298018169      
    1                        1                        20                       0                        0.07079655446543297      
    1                        1                        20                       0.1                      0.07286704639139795      
    2                        0.1                      0                        0                        0.07078663749666488      
    2                        0.1                      0                        0.1                      0.07284943819285646 
    

    我希望从每个参数中的最小值对数据进行排序。

    3 回复  |  直到 5 年前
        1
  •  1
  •   Massifox    4 年前

    如果要对单列上的ndarray排序,请使用 np.argsort

    给定以下矩阵:

    m = np.array([[5., 0.1, 3.4],
               [7., 0.3, 6.8],
               [3., 0.2, 5.6]])
    

    此代码基于列0对矩阵m进行排序:

    m[m[:,0].argsort(kind='mergesort')]
    

    结果:

    array([[3. , 0.2, 5.6],
           [5. , 0.1, 3.4],
           [7. , 0.3, 6.8]])
    

    如果要在多个列上使用 np.lexsort

    a = np.array([[1,20,200], [1,30,100], [1,10,300]])
    array([[  1,  20, 200],
           [  1,  30, 100],
           [  1,  10, 300]])
    

    按列1和列0排序:

    a[np.lexsort((a[:,0],a[:,1]))]
    # output:
    array([[  1,  10, 300],
           [  1,  20, 200],
           [  1,  30, 100]])
    

    注意 :的 右最后一列 (如果键是二维数组,则为行)是主排序键。

    按所有列排序(从右侧开始):

    a[np.lexsort((a[:,0], a[:,1],a[:,2]))]
    # output:
    array([[  1,  30, 100],
           [  1,  20, 200],
           [  1,  10, 300]])
    

    a[np.lexsort(list(map(tuple,np.column_stack(a))))]
    # output:
    array([[  1,  30, 100],
           [  1,  20, 200],
           [  1,  10, 300]])
    

    其他选择:熊猫对你的特定问题是个好主意?

    另一个选择是切换到熊猫。这是可行的,但速度慢了一个数量级。下面是对执行时间的一些测试:

    a = np.array([[1,20,200]*1000, [1,30,100]*1000, [1,10,300]*1000])
    

    熊猫版:

    %%timeit
    pd.DataFrame(a).sort_values(list(range(a.shape[1]))).values
    # 3.66 s ± 110 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    

    Numpy版本:

    %%timeit
    a[np.lexsort((a[:,0], a[:,1],a[:,2]))]
    # 39.6 µs ± 12.1 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    正如你所看到的,从numpy的微秒到基于熊猫的版本秒(大约慢100万倍)。
    您可以选择:)

        2
  •  1
  •   Paul Panzer    5 年前

    你可以用 lexsort

    original[np.lexsort(np.rot90(original))]
    
        3
  •  1
  •   Quang Hoang    5 年前

    一个使用 pandas sort_values :

    pd.DataFrame(a).sort_values(list(range(a.shape[1]))).values
    

    输出:

    array([[ 1.        ,  0.1       , 20.        ,  0.3       ,  0.0781932 ],
           [ 1.        ,  1.        ,  5.        ,  0.4       ,  0.08652187],
           [ 1.        ,  1.        , 10.        ,  0.2       ,  0.07550707],
           [ 1.        ,  1.        , 15.        ,  0.3       ,  0.0781932 ],
           [ 1.        ,  1.        , 15.        ,  0.4       ,  0.08047399],
           [ 1.        ,  1.        , 15.        ,  0.5       ,  0.08204023],
           [ 1.        ,  1.        , 20.        ,  0.        ,  0.07079655],
           [ 1.        ,  1.        , 20.        ,  0.1       ,  0.07286705],
           [ 2.        ,  0.1       ,  0.        ,  0.        ,  0.07078664],
           [ 2.        ,  0.1       ,  0.        ,  0.1       ,  0.07284944]])