将每行的最后一个非零元素设置为零 - NumPy
Set last non-zero element of each row to zero - NumPy
我有一个数组 A:
A = array([[1, 2, 3,4], [5,6,7,0] , [8,9,0,0]])
我想将每一行的最后一个非零值改为 0
A = array([[1, 2, 3,0], [5,6,0,0] , [8,0,0,0]])
如何为任何 n*m numpy 数组编写代码?
谢谢,S ;-)
方法 #1
一种基于cumsum
和argmax
的方法-
A[np.arange(A.shape[0]),(A!=0).cumsum(1).argmax(1)] = 0
样本运行-
In [59]: A
Out[59]:
array([[2, 0, 3, 4],
[5, 6, 7, 0],
[8, 9, 0, 0]])
In [60]: A[np.arange(A.shape[0]),(A!=0).cumsum(1).argmax(1)] = 0
In [61]: A
Out[61]:
array([[2, 0, 3, 0],
[5, 6, 0, 0],
[8, 0, 0, 0]])
方法 #2
另一个基于argmax
,希望更有效率-
A[np.arange(A.shape[0]),A.shape[1] - 1 - (A[:,::-1]!=0).argmax(1)] = 0
说明
argmax
的用途之一是获取数组中 max
元素沿轴 第一次 出现的 ID。在第一种方法中,我们沿行获取 cumsum 并获取第一个最大 ID,它表示最后一个非零元素。这是因为剩余元素上的 cumsum
不会增加最后一个非零元素之后的总和值。
让我们以更详细的方式重新运行那个案例 -
In [105]: A
Out[105]:
array([[2, 0, 3, 4],
[5, 6, 7, 0],
[8, 9, 0, 0]])
In [106]: (A!=0)
Out[106]:
array([[ True, False, True, True],
[ True, True, True, False],
[ True, True, False, False]], dtype=bool)
In [107]: (A!=0).cumsum(1)
Out[107]:
array([[1, 1, 2, 3],
[1, 2, 3, 3],
[1, 2, 2, 2]])
In [108]: (A!=0).cumsum(1).argmax(1)
Out[108]: array([3, 2, 1])
最后,我们使用 fancy-indexing
将它们用作列索引以在 A
中设置适当的元素。
在第二种方法中,当我们在布尔数组上使用 argmax
时,我们只是得到了 True
的第一次出现,我们在输入数组的行翻转版本上使用了它。因此,我们将拥有原始顺序中的最后一个非零元素。其余的想法是一样的。
一种方法是使用所需的行和列索引显式构成数组:
A = np.array([[1, 2, 3,4], [5,6,7,0] , [8,9,0,0]])
row_inds = np.arange(A.shape[0])
col_inds = np.arange(A.shape[1])
nonzero_col_inds = (A > 0) * col_inds
max_nonzero_col_inds = np.max(nonzero_col_inds, 1)
A[row_inds, max_nonzero_col_inds] = 0
我有一个数组 A:
A = array([[1, 2, 3,4], [5,6,7,0] , [8,9,0,0]])
我想将每一行的最后一个非零值改为 0
A = array([[1, 2, 3,0], [5,6,0,0] , [8,0,0,0]])
如何为任何 n*m numpy 数组编写代码? 谢谢,S ;-)
方法 #1
一种基于cumsum
和argmax
的方法-
A[np.arange(A.shape[0]),(A!=0).cumsum(1).argmax(1)] = 0
样本运行-
In [59]: A
Out[59]:
array([[2, 0, 3, 4],
[5, 6, 7, 0],
[8, 9, 0, 0]])
In [60]: A[np.arange(A.shape[0]),(A!=0).cumsum(1).argmax(1)] = 0
In [61]: A
Out[61]:
array([[2, 0, 3, 0],
[5, 6, 0, 0],
[8, 0, 0, 0]])
方法 #2
另一个基于argmax
,希望更有效率-
A[np.arange(A.shape[0]),A.shape[1] - 1 - (A[:,::-1]!=0).argmax(1)] = 0
说明
argmax
的用途之一是获取数组中 max
元素沿轴 第一次 出现的 ID。在第一种方法中,我们沿行获取 cumsum 并获取第一个最大 ID,它表示最后一个非零元素。这是因为剩余元素上的 cumsum
不会增加最后一个非零元素之后的总和值。
让我们以更详细的方式重新运行那个案例 -
In [105]: A
Out[105]:
array([[2, 0, 3, 4],
[5, 6, 7, 0],
[8, 9, 0, 0]])
In [106]: (A!=0)
Out[106]:
array([[ True, False, True, True],
[ True, True, True, False],
[ True, True, False, False]], dtype=bool)
In [107]: (A!=0).cumsum(1)
Out[107]:
array([[1, 1, 2, 3],
[1, 2, 3, 3],
[1, 2, 2, 2]])
In [108]: (A!=0).cumsum(1).argmax(1)
Out[108]: array([3, 2, 1])
最后,我们使用 fancy-indexing
将它们用作列索引以在 A
中设置适当的元素。
在第二种方法中,当我们在布尔数组上使用 argmax
时,我们只是得到了 True
的第一次出现,我们在输入数组的行翻转版本上使用了它。因此,我们将拥有原始顺序中的最后一个非零元素。其余的想法是一样的。
一种方法是使用所需的行和列索引显式构成数组:
A = np.array([[1, 2, 3,4], [5,6,7,0] , [8,9,0,0]])
row_inds = np.arange(A.shape[0])
col_inds = np.arange(A.shape[1])
nonzero_col_inds = (A > 0) * col_inds
max_nonzero_col_inds = np.max(nonzero_col_inds, 1)
A[row_inds, max_nonzero_col_inds] = 0