从numpy矩阵中删除/提取子矩阵的最快方法

时间:2018-12-11 03:10:16

标签: python arrays numpy

我有一个NxN的方阵(N通常> 500)。它是使用numpy数组构造的。

我需要提取一个新矩阵,该矩阵的第i列和第i行已从该矩阵中删除。新的矩阵是(N-1)x(N-1)。

我目前正在使用以下代码提取此矩阵:

            new_mat = np.delete(old_mat,idx_2_remove,0)
            new_mat = np.delete(old_mat,idx_2_remove,1)

我也尝试使用:

row_indices = [i for i in range(0,idx_2_remove)]
row_indices += [i for i in range(idx_2_remove+1,N)]
col_indices = row_indices
rows = [i for i in row_indices for j in col_indices]
cols = [j for i in row_indices for j in col_indices]

old_mat[(rows, cols)].reshape(len(row_indices), len(col_indices))

但是我发现这比在前者中使用np.delete()要慢。对于我的应用程序,前者仍然相当慢。

是否有更快的方法来完成我想要的?

编辑1: 似乎以下内容甚至比以上两个要快,但幅度不大:

new_mat = old_mat[row_indices,:][:,col_indices]

1 个答案:

答案 0 :(得分:1)

以下是我迅速写的3种选择:

重复delete

def foo1(arr, i):
    return np.delete(np.delete(arr, i, axis=0), i, axis=1)

最大程度地使用切片(可能需要进行一些边缘检查):

def foo2(arr,i):
    N = arr.shape[0]
    res = np.empty((N-1,N-1), arr.dtype)
    res[:i, :i] = arr[:i, :i]
    res[:i, i:] = arr[:i, i+1:]
    res[i:, :i] = arr[i+1:, :i]
    res[i:, i:] = arr[i+1:, i+1:]
    return res

高级索引编制:

def foo3(arr,i):
    N = arr.shape[0]
    idx = np.r_[:i,i+1:N]
    return arr[np.ix_(idx, idx)]

测试它们是否有效

In [874]: x = np.arange(100).reshape(10,10)
In [875]: np.allclose(foo1(x,5),foo2(x,5))
Out[875]: True
In [876]: np.allclose(foo1(x,5),foo3(x,5))
Out[876]: True

比较时间:

In [881]: timeit foo1(arr,100).shape
4.98 ms ± 190 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [882]: timeit foo2(arr,100).shape
526 µs ± 1.57 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [883]: timeit foo3(arr,100).shape
2.21 ms ± 112 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

因此,即使代码更长,切片速度也最快。看起来np.delete的工作方式类似于foo3,但一次只能显示一个维度。