0

I'm trying to index some matrix, y, and then reindex that result with some boolean statement and set the corresponding elements in y to 0. The dummy code I'm using to test this indexing scheme is shown below.

x=np.zeros([5,4])+0.1;
y=x;
print(x)
m=np.array([0,2,3]);
y[0:4,m][y[0:4,m]<0.5]=0;
print(y)

I'm not sure why it does not work. The output I want:

[[ 0.1  0.1  0.1  0.1]
 [ 0.1  0.1  0.1  0.1]
 [ 0.1  0.1  0.1  0.1]
 [ 0.1  0.1  0.1  0.1]
 [ 0.1  0.1  0.1  0.1]]
[[ 0.   0.1  0.   0. ]
 [ 0.   0.1  0.   0. ]
 [ 0.   0.1  0.   0. ]
 [ 0.   0.1  0.   0. ]
 [ 0.1  0.1  0.1  0.1]]

But what I actually get:

[[ 0.1  0.1  0.1  0.1]
 [ 0.1  0.1  0.1  0.1]
 [ 0.1  0.1  0.1  0.1]
 [ 0.1  0.1  0.1  0.1]
 [ 0.1  0.1  0.1  0.1]]
[[ 0.1  0.1  0.1  0.1]
 [ 0.1  0.1  0.1  0.1]
 [ 0.1  0.1  0.1  0.1]
 [ 0.1  0.1  0.1  0.1]
 [ 0.1  0.1  0.1  0.1]]

I'm sure I'm missing some under-the-hood details that explains why this does not work. Interestingly, if you replace m with :, then the assignment works. For some reason, selecting a subset of the columns does not let me assign the zeros.

If someone could explain what's going on and help me find an alternative solution (hopefully one that does not involve generating a temporary numpy array since my actual y will be really huge), I would really appreciate it! Thank you!

EDIT: y[0:4,:][y[0:4,:]<0.5]=0; y[0:4,0:3][y[0:4,0:3]<0.5]=0; etc.

all work as expected. It seems the issue is when you index with a list of some kind.

4
  • Could you maybe use some random numbers instead of all 0.1, something like np.random.rand(5,4) as the input and show us the expected output? Commented Nov 13, 2016 at 9:48
  • I originally tested with all random numbers which is where I initially encountered the issue. I switched to all 0.1 just because it was more reproducible. Commented Nov 13, 2016 at 9:54
  • You could use np.random.seed(1234) at the start to have reproducible random numbers. Commented Nov 13, 2016 at 9:56
  • The double y[...][...]= creates a copy, not a view. m is an array, not a slice. Commented Nov 13, 2016 at 11:01

1 Answer 1

0

Make an array (this is one of my favorites because the values differ):

In [845]: x=np.arange(12).reshape(3,4)
In [846]: x
Out[846]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
In [847]: m=np.array([0,2,3])
In [848]: x[:,m]
Out[848]: 
array([[ 0,  2,  3],
       [ 4,  6,  7],
       [ 8, 10, 11]])
In [849]: x[:,m][:2,:]=0
In [850]: x
Out[850]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

No change. But if I do the indexing in one step, it changes.

In [851]: x[:2,m]=0
In [852]: x
Out[852]: 
array([[ 0,  1,  0,  0],
       [ 0,  5,  0,  0],
       [ 8,  9, 10, 11]])

it also works if I reverse the order:

In [853]: x[:2,:][:,m]=10
In [854]: x
Out[854]: 
array([[10,  1, 10, 10],
       [10,  5, 10, 10],
       [ 8,  9, 10, 11]])

x[i,j] is executed as x.__getitem__((i,j)). x[i,j]=v as x.__setitem__((i,j),v).

x[i,j][k,l]=v is x.__getitem__((i,j)).__setitem__((k,l),v).

The set applies to the value produced by the get. If the get returns a view, then the change affects x. But if it produces a copy, the change does not affect x.

With array m, y[0:4,m] produces a copy (do I need to demonstrate that?). y[0:4,:] produces a view.

So in short, if the first indexing produces a view the second indexed assignment works. But if produces a copy, the second has no effect.

1
  • This makes sense, thank you. In my case, is it possible to do what I want in one indexing step? Commented Nov 13, 2016 at 19:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.