 <p>Assuming that you are looking to set all elements for each row until the last negative element to be set to zero (as per the expected output listed in the question for a sample case), two approaches could be suggested here.</p> <p><strong>Approach #1</strong></p> <p>This one is based on <a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.cumsum.html"><code>np.cumsum</code></a> to generate a mask of elements to be set to zeros as listed next -</p> <pre><code># Get boolean mask with TRUEs for each row starting at the first element and # ending at the last negative element mask = (np.cumsum(A2[:,::-1]&lt;0,1)&gt;0)[:,::-1] # Use mask to set all such al TRUEs to zeros as per the expected output in OP A2[mask] = 0 </code></pre> <p>Sample run -</p> <pre><code>In [280]: A2 = np.random.randint(-4,10,(6,7)) # Random input 2D array In [281]: A2 Out[281]: array([[-2, 9, 8, -3, 2, 0, 5], [-1, 9, 5, 1, -3, -3, -2], [ 3, -3, 3, 5, 5, 2, 9], [ 4, 6, -1, 6, 1, 2, 2], [ 4, 4, 6, -3, 7, -3, -3], [ 0, 2, -2, -3, 9, 4, 3]]) In [282]: A2[(np.cumsum(A2[:,::-1]&lt;0,1)&gt;0)[:,::-1]] = 0 # Use mask to set zeros In [283]: A2 Out[283]: array([[0, 0, 0, 0, 2, 0, 5], [0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 5, 5, 2, 9], [0, 0, 0, 6, 1, 2, 2], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 9, 4, 3]]) </code></pre> <p><strong>Approach #2</strong></p> <p>This one starts with the idea of finding the last negative element indices from <a href="http://stackoverflow.com/a/31084951/3293881"><code>@tom10's answer</code></a> and develops into a mask finding method using <a href="http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html"><code>broadcasting</code></a> to get us the desired output, similar to <code>approach #1</code>.</p> <pre><code># Find last negative index for each row last_idx = A2.shape[1] - 1 - np.argmax(A2[:,::-1]&lt;0, axis=1) # Find the invalid indices (rows with no negative indices) invalid_idx = A2[np.arange(A2.shape[0]),last_idx]&gt;=0 # Set the indices for invalid ones to "-1" last_idx[invalid_idx] = -1 # Boolean mask with each row starting with TRUE as the first element # and ending at the last negative element mask = np.arange(A2.shape[1]) &lt; (last_idx[:,None] + 1) # Set masked elements to zeros, for the desired output A2[mask] = 0 </code></pre> <hr> <p>Runtime tests -</p> <p>Function defintions:</p> <pre><code>def broadcasting_based(A2): last_idx = A2.shape[1] - 1 - np.argmax(A2[:,::-1]&lt;0, axis=1) last_idx[A2[np.arange(A2.shape[0]),last_idx]&gt;=0] = -1 A2[np.arange(A2.shape[1]) &lt; (last_idx[:,None] + 1)] = 0 return A2 def cumsum_based(A2): A2[(np.cumsum(A2[:,::-1]&lt;0,1)&gt;0)[:,::-1]] = 0 return A2 </code></pre> <p>Runtimes:</p> <pre><code>In [379]: A2 = np.random.randint(-4,10,(100000,100)) ...: A2c = A2.copy() ...: In [380]: %timeit broadcasting_based(A2) 10 loops, best of 3: 106 ms per loop In [381]: %timeit cumsum_based(A2c) 1 loops, best of 3: 167 ms per loop </code></pre> <p>Verify results -</p> <pre><code>In [384]: A2 = np.random.randint(-4,10,(100000,100)) ...: A2c = A2.copy() ...: In [385]: np.array_equal(broadcasting_based(A2),cumsum_based(A2c)) Out[385]: True </code></pre>