1

I've run into this interaction with arrays that I'm a little confused. I can work around it, but for my own understanding, I'd like to know what is going on.

Essentially, I have a datafile that I'm trying to tailor so I can run this as an input for some code I've already written. This involves some calculations on some columns, rows, etc. In particular, I also need to rearrange some elements, where the original array isn't being modified as I expect it would.

import numpy as np

ex_data = np.arange(12).reshape(4,3)
ex_data[2,0] = 0                #Constructing some fake data

ex_data[ex_data[:,0] == 0][:,1] = 3

print ex_data

Basically, I look in a column of interest, collect all the rows where that column contains a parameter value of interest and just reassigning values.

With the snippet of code above, I would expect ex_data to have it's column 1 elements, conditional if it's column 0 element is equal to 0, to be assigned a value of 3. However what I'm seeing is that there is no effect at all.

>>> ex_data
array([[ 0,  1,  2],
   [ 3,  4,  5],
   [ 0,  7,  8],
   [ 9, 10, 11]])

In another case, if I don't 'slice', my 'sliced' data file, then the reassignment goes on as normal.

ex_data[ex_data[:,0] == 0] = 3
print ex_data

Here I'd expect my entire row, conditional to where column 0 is equal to 0, be populated with 3. This is what you see.

>>> ex_data
array([[ 3,  3,  3],
   [ 3,  4,  5],
   [ 3,  3,  3],
   [ 9, 10, 11]])

Can anyone explain the interaction?

3
  • ex_data[ex_data[:,0] == 0] is advanced indexing, so makes a copy. It is not a view. Commented Aug 24, 2018 at 4:02
  • What would be your workaround @hpaulj? Commented Aug 24, 2018 at 4:04
  • figure out how to do the indexing with just one [] set. x[...] = ... works with advanced indexing. Commented Aug 24, 2018 at 4:07

1 Answer 1

3
In [368]: ex_data
Out[368]: 
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 0,  7,  8],
       [ 9, 10, 11]])

The column 0 test:

In [369]: ex_data[:,0]==0
Out[369]: array([ True, False,  True, False])

That boolean mask can be applied to the rows as:

In [370]: ex_data[ex_data[:,0]==0,0]
Out[370]: array([0, 0])        # the 0's you expected

In [371]: ex_data[ex_data[:,0]==0,1]
Out[371]: array([1, 7])        # the col 1 values you want to replace

In [372]: ex_data[ex_data[:,0]==0,1] = 3
In [373]: ex_data
Out[373]: 
array([[ 0,  3,  2],
       [ 3,  4,  5],
       [ 0,  3,  8],
       [ 9, 10, 11]])

The indexing you tried:

In [374]: ex_data[ex_data[:,0]==0]
Out[374]: 
array([[0, 3, 2],
       [0, 3, 8]])

produces a copy. Assigning ...[:,1]=3 just changes that copy, not the original array. Fortunately in this case, it is easy to use

ex_data[ex_data[:,0]==0,1]

instead of

ex_data[ex_data[:,0]==0][:,1]
Sign up to request clarification or add additional context in comments.

Comments

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.