我有一个2D数组(NumPy数组),并希望得到一个子数组,它是切断给定行和列的结果。
作为一个例子,我找到了一种方法:
In [111]: mat
Out[111]:
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25]])
In [112]: np.delete(np.delete(mat, 3, 1), 0,0)
Out[112]:
array([[ 6, 7, 8, 10],
[11, 12, 13, 15],
[16, 17, 18, 20],
[21, 22, 23, 25]])
这取出了第0行和第3列。但是,我不认为这非常漂亮,据我所知,它必须为两个额外的数组分配空间,每个数据从{{返回一个1}}。
所以问题是,是否有某种方法可以以更高的读取和内存效率方式获得所需的结果?理想情况下,某些东西只能提供对数组正确元素的引用,而不是完整副本。请注意,该示例不是我需要的数组,答案应适用于删除行np.delete
和列n x n
的{{1}}。
答案 0 :(得分:1)
您可以使用np.column_stack
进行简单的索引编制:
>>> np.column_stack((A[1:,:3],A[1:,4:]))
array([[ 6, 7, 8, 10],
[11, 12, 13, 15],
[16, 17, 18, 20],
[21, 22, 23, 25]])
答案 1 :(得分:1)
实际删除
要实际删除元素,请使用broadcasted boolean indexing
与np.in1d
进行删除 -
In [220]: def cut_valid_array(mat,row_cut,col_cut):
...: m,n = mat.shape
...: row_mask = ~np.in1d(np.arange(m),row_cut)
...: col_mask = ~np.in1d(np.arange(n),col_cut)
...: return mat[(row_mask[:,None]*col_mask)].reshape(-1,n-1)
...:
In [221]: mat = np.random.randint(0,100,(1000,1000))
In [222]: %timeit np.delete(np.delete(mat, col_cut, 1), row_cut,0)
10 loops, best of 3: 26.3 ms per loop
In [223]: mat = np.random.randint(0,100,(1000,1000))
In [224]: %timeit cut_valid_array(mat,row_cut,col_cut)
100 loops, best of 3: 7.48 ms per loop
运行时测试 -
m,n = mat.shape
row_mask = ~np.in1d(np.arange(m),row_cut)
col_mask = ~np.in1d(np.arange(n),col_cut)
mask2D = (row_mask[:,None]*col_mask)
保持有效的面具
您还可以创建有效元素的2D蒙版,当然还有与输入数组相同的形状,以获得更多内存和时间效率的方法,如下所示 -
In [225]: def cut_valid_mask(mat,row_cut,col_cut):
...: m,n = mat.shape
...: row_mask = ~np.in1d(np.arange(m),row_cut)
...: col_mask = ~np.in1d(np.arange(n),col_cut)
...: return (row_mask[:,None]*col_mask)
...:
In [226]: mat = np.random.randint(0,100,(1000,1000))
In [227]: %timeit np.delete(np.delete(mat, col_cut, 1), row_cut,0)
10 loops, best of 3: 27 ms per loop
In [228]: mat = np.random.randint(0,100,(1000,1000))
In [229]: %timeit cut_valid_mask(mat,row_cut,col_cut)
1000 loops, best of 3: 414 µs per loop
运行时测试 -
{{1}}
答案 2 :(得分:1)
我认为你的解决方案不是那么糟糕,问题在于删除任意行"和"列"你正在破坏数组的结构(查看strides),获得具有该新结构的数组的唯一方法是重新分配它。
通常只有certain slicing operations才能返回数组的内存效率视图,例如使用常规切片(没有花哨的东西,例如列表)。
答案 3 :(得分:0)
怎么样
mat[[1,2,3,4],:][:,[0,1,2,4]]
应该给出相同的结果吗?