【问题标题】:re-arranging entries in 2d array based on certain columns根据某些列重新排列二维数组中的条目
【发布时间】:2019-09-20 21:45:54
【问题描述】:

假设我有一个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 

我希望数据从每个参数中的最小值开始排序。

【问题讨论】:

    标签: python numpy multidimensional-array


    【解决方案1】:

    如果你想使用np.argsort对单列排序ndarray

    给定以下矩阵:

    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在多列上对ndarray进行排序

    给定:

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

    其他选项:Pandas 对您的具体问题来说是个好主意?

    另一种选择是切换到熊猫。它有效,但速度要慢一些数量级。以下是一些关于执行时间的测试:

    基准数据:

    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 的微秒级到基于 pandas 的版本的秒级(慢了大约 100 万倍)。
    选择是你的:)

    【讨论】:

    • 是的,但是在每个参数中(例如3),还有多个其他参数。我也想按顺序对它们进行排序。例如array([[3, 0.2, 5.6],[3, 0.3, 3.4],[3, 0.4, 3.5],[5,0.1,3.4],[5,0.3,5.3],[5,0.6,9.5],[7,0.3,6.8]])
    • 现在我明白你的意思了,我正在更新我的答案。
    • 对于a[np.lexsort(list(map(tuple,np.column_stack(a))))],它以与我想要的相反的顺序对顺序进行排序(我希望最左边的列是“外部”列)。所以我需要a[np.lexsort((a[:,2],a[:,1],a[:,0]))。如何为任意数量的列重写这个?
    • 这个a[np.lexsort(( a[:,0],a[:,1],a[:,2]))] 等于a[np.lexsort(list(map(tuple, np.column_stack(a))))] 并且这个a[np.lexsort(( a[:,2],a[:,1],a[:,0]))] 等于a[np.lexsort(list(map(tuple, reversed(np.column_stack(a)))))]。我更新了答案,因为可能不清楚最后一个右列是主排序键。我是否回答了您的问题并澄清了您的疑问? @物理学家
    • 是的,现在完美了。
    【解决方案2】:

    你可以使用lexsort:

    original[np.lexsort(np.rot90(original))]
    

    【讨论】:

      【解决方案3】:

      一个使用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]])
      

      【讨论】:

        猜你喜欢
        • 2019-01-06
        • 1970-01-01
        • 1970-01-01
        • 2019-06-23
        • 1970-01-01
        • 2014-08-21
        • 1970-01-01
        • 2017-11-25
        • 1970-01-01
        相关资源
        最近更新 更多