kevqnp
kevqnp

Reputation: 163

Sliced numpy array does not modify original array

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?

Upvotes: 1

Views: 1511

Answers (1)

hpaulj
hpaulj

Reputation: 231385

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]

Upvotes: 3

Related Questions