Indexing and Replacing NumPy Arrays

I have a 3d numpy array as follows:

(3L, 5L, 5L) 

If there is one element in three-dimensional positions, for example, [150, 160, 170] . How to convert them all to [0,0,0] ?

 import numpy as np a = np.ones((3,5,5)) a[0,2:4,2:4] = 150 a[0,0:1,0:1] = 150 #important! a[1,2:4,2:4] = 160 a[2,2:4,2:4] = 170 print a 

Expected Result:

 [[[ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 0. 0. 1.] [ 1. 1. 0. 0. 1.] [ 1. 1. 1. 1. 1.]] [[ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 0. 0. 1.] [ 1. 1. 0. 0. 1.] [ 1. 1. 1. 1. 1.]] [[ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 0. 0. 1.] [ 1. 1. 0. 0. 1.] [ 1. 1. 1. 1. 1.]]] 
+1
arrays numpy scipy scikit-image
source share
2 answers

First, I convert to a stack of triples:

 b = np.reshape(a.transpose(2, 1, 0), [25,3]) 

Then find the desired values:

 idx = np.where((b == np.array([150, 160, 170])).all(axis=1)) 

And replace the desired value:

 b[idx] = 0 

And finally, back to the original form:

 c = np.reshape(b, [5, 5, 3]).transpose(2, 1, 0) 
+2
source share

Build your a :

 In [48]: a=np.ones((3,5,5)) In [49]: a[0,2:4,2:4]=150 In [50]: a[1,2:4,2:4]=160 In [51]: a[2,2:4,2:4]=170 In [52]: a Out[52]: array([[[ 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1.], [ 1., 1., 150., 150., 1.], [ 1., 1., 150., 150., 1.], [ 1., 1., 1., 1., 1.]], [[ 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1.], [ 1., 1., 160., 160., 1.], [ 1., 1., 160., 160., 1.], [ 1., 1., 1., 1., 1.]], [[ 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1.], [ 1., 1., 170., 170., 1.], [ 1., 1., 170., 170., 1.], [ 1., 1., 1., 1., 1.]]]) 

Booleans of all places where the values ​​are in the first dimension [150,160,170] . The key is to deploy this to 3d, shape (3,1,1) , which can be passed to (3,5,5) and compared to a :

 In [53]: I = a==np.array([150,160,170])[:,None,None] In [54]: I Out[54]: array([[[False, False, False, False, False], [False, False, False, False, False], [False, False, True, True, False], [False, False, True, True, False], [False, False, False, False, False]], [[False, False, False, False, False], [False, False, False, False, False], [False, False, True, True, False], [False, False, True, True, False], [False, False, False, False, False]], [[False, False, False, False, False], [False, False, False, False, False], [False, False, True, True, False], [False, False, True, True, False], [False, False, False, False, False]]], dtype=bool) 

Now it’s trivial to change all these slots with True to 0 :

 In [55]: a[I]=0 In [56]: a Out[56]: array([[[ 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1.], [ 1., 1., 0., 0., 1.], [ 1., 1., 0., 0., 1.], [ 1., 1., 1., 1., 1.]], [[ 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1.], [ 1., 1., 0., 0., 1.], [ 1., 1., 0., 0., 1.], [ 1., 1., 1., 1., 1.]], [[ 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1.], [ 1., 1., 0., 0., 1.], [ 1., 1., 0., 0., 1.], [ 1., 1., 1., 1., 1.]]]) 

Looking at the comments on the deleted answer, I see that you really need a case where all 3 values ​​match. That is, contrary to your example, there may be other slots a[0,...] - 150, etc., which you do not want to change.

You can still work with this I just by taking all on the 1st axis:

 In [58]: a[:,I.all(axis=0)]=2 In [59]: a Out[59]: array([[[ 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1.], [ 1., 1., 2., 2., 1.], [ 1., 1., 2., 2., 1.], [ 1., 1., 1., 1., 1.]], [[ 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1.], [ 1., 1., 2., 2., 1.], [ 1., 1., 2., 2., 1.], [ 1., 1., 1., 1., 1.]], [[ 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1.], [ 1., 1., 2., 2., 1.], [ 1., 1., 2., 2., 1.], [ 1., 1., 1., 1., 1.]]]) 

Conceptually, my answer is no different from what was accepted. This converts the array to 2d, so matching can be done using 1d [150,160,170] . In fact, it is automatically converted to (1,3) , which can be passed again to the array (25,3) . Transposing and rebuilding is a convenient way to standardize the format of such problems, although often this is not required.


This can help break up the last action:

 In [60]: J=I.all(axis=0) In [61]: J Out[61]: array([[False, False, False, False, False], [False, False, False, False, False], [False, False, True, True, False], [False, False, True, True, False], [False, False, False, False, False]], dtype=bool) In [62]: a[:, J] = 3 

or use np.where to convert a boolean array to 2 index lists:

 In [73]: jj=np.where(J) In [74]: jj Out[74]: (array([2, 2, 3, 3], dtype=int32), array([2, 3, 2, 3], dtype=int32)) In [75]: a[:, jj[0], jj[1]] = 4 

a[:,jj] does not work, but a[(slice(None),)+jj] does. This last expression creates a three-element tuple equivalent to [75].

I could also extend J to a size and shape corresponding to a :

 In [90]: K=J[None,...].repeat(3,0) In [91]: K Out[91]: array([[[False, False, False, False, False], [False, False, False, False, False], [False, False, True, True, False], [False, False, True, True, False], [False, False, False, False, False]], [[False, False, False, False, False], ....]], dtype=bool) 

and use a[K] .

+2
source share

All Articles