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

Python 从numpy矩阵中删除/提取子矩阵的最快方法,python,arrays,numpy,Python,Arrays,Numpy,我有一个平方矩阵,它是NxN,通常大于500。它是使用numpy数组构造的 我需要提取一个新的矩阵,它从这个矩阵中删除了第I列和第I行。新矩阵为N-1xN-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

我有一个平方矩阵,它是NxN,通常大于500。它是使用numpy数组构造的

我需要提取一个新的矩阵,它从这个矩阵中删除了第I列和第I行。新矩阵为N-1xN-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]

下面是我快速写下的3个备选方案:

重复删除:

最大限度地使用切片可能需要一些边缘检查:

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类似,但一次只能执行一个维度。

如果仅为500x500左右,则复制时间通常可以忽略不计。对于较大的矩阵,我认为创建一个空数组并将4个切片复制到其中应该相当快。我认为500x500是较小的。最大的将是50000x50000。我处理的大多数案例可能都在10000x1000左右。你觉得编辑中的方法怎么样?i、 例如,new_mat=old_mat[row_index,:][:,col_index]根据矢量化的内容,使用切片而不是花哨的索引应该更快,但这需要进行基准测试。无论如何,索引两次可能要花费两倍的时间,您可能希望至少将这两个索引一起广播,就像old_mat[row_Indexes[:,None],col_Indexes],我会尝试一下。谢谢我以前从未尝试过切片,但我会看一看。我使用旧的_mat[row_index[:,None],col_index]时出错。它是说new_mat=old_mat[row_idx[:,None],col_idx]类型错误:列表索引必须是整数或切片,而不是元组
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)