首页 > 解决方案 > 根据某些列重新排列二维数组中的条目

问题描述

假设我有一个M x Nnumpy 数组,其中每一行代表一个数据条目,第一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 

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

标签: pythonnumpymultidimensional-array

解决方案


如果您想使用 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)

数字版本:

%%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 万倍)。
这是你的选择 :)


推荐阅读