1

I'm not sure I understand why this doesn't work :

a = np.zeros((10, ))

# first slicing array
pos1 = np.zeros((10, ), dtype=np.bool)
pos1[::2] = True

a[pos1] = 1.
print a
# returns [ 1.  0.  1.  0.  1.  0.  1.  0.  1.  0.]


# second slicing array
pos2 = np.zeros((5, ), dtype=np.bool)
pos2[::2] = True

a[pos1][pos2] = 2.

print a
# still returns [ 1.  0.  1.  0.  1.  0.  1.  0.  1.  0.]

why does the second slicing didn't affect the full array? I thought a[pos1] was just a "view" of the subpart of the original array... Am I missing something?

(this example is just a simple example with no real use, it is just to try to understand cause I'm using this kind of syntax a lot and I didn't expect this result)

3
  • Probably has to do with it being an assignment, .... being on the left-hand-side. Commented Aug 18, 2015 at 4:16
  • Just looking at it, it appears that you are trying to assign a value to a subset of a 2d array. During assignment, it must not be creating a temporary array from a[pos1]. You would have to dig into the docs or maybe even the source to find the answer. Commented Aug 18, 2015 at 4:33
  • 1
    Boolean indexing is a type of "advanced indexing"; this is not the same as slicing and does not give a view into the original array. Commented Aug 18, 2015 at 5:19

2 Answers 2

2

It's the same issue as in recent Numpy doesn't change value of an array element after masking

You are using a boolean mask, so a[pos1] is a copy, not a slice.

The first set works because it is a direct call to __setitem__:

a[pos1] = 1.
a.__setitem__(pos1) = 1

The second does not because the set applies to a[pos1], a copy:

a[pos1][pos2] = 2.
a.__getitem__(pos1).__setitem__(pos2)

a[::2][pos2]=3 does work because a[::2] is a slice - even though it produces the same values as a[pos1].

One way to check whether something is a copy or view is to look at the array's data pointer

 a.__array_interface__['data']
 a[pos1].__array_interface__['data'] # will be different
 a[::2].__array_interface__['data']  # should be the same
Sign up to request clarification or add additional context in comments.

1 Comment

thank you! Sorry for the duplicate, I didn't find this question/answer... same problem indeed! :)
0

Take a look at the python byte code (outputs of dis) when we define the following three functions:

In [187]: def b():
    a[pos1][pos2]=2
    return a

In [188]: dis.dis(b)
  2           0 LOAD_CONST               1 (2)
              3 LOAD_GLOBAL              0 (a)
              6 LOAD_GLOBAL              1 (pos1)
              9 BINARY_SUBSCR       
             10 LOAD_GLOBAL              2 (pos2)
             13 STORE_SUBSCR        

  3          14 LOAD_GLOBAL              0 (a)
             17 RETURN_VALUE        

In [189]: b()
Out[189]: array([ 1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.])




In [190]: def c():
    e=a.copy()
    e[pos1][pos2]=2
    return e

In [191]: dis.dis(c)
  2           0 LOAD_GLOBAL              0 (a)
              3 LOAD_ATTR                1 (copy)
              6 CALL_FUNCTION            0
              9 STORE_FAST               0 (e)

  3          12 LOAD_CONST               1 (2)
             15 LOAD_FAST                0 (e)
             18 LOAD_GLOBAL              2 (pos1)
             21 BINARY_SUBSCR       
             22 LOAD_GLOBAL              3 (pos2)
             25 STORE_SUBSCR        

  4          26 LOAD_FAST                0 (e)
             29 RETURN_VALUE 

In [191]: c()
Out[191]: array([ 1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.])




In [192]: def d():
    f=a[pos1]
    f[pos2]=2
    return f

In [193]: dis.dis(d)
  2           0 LOAD_GLOBAL              0 (a)
              3 LOAD_GLOBAL              1 (pos1)
              6 BINARY_SUBSCR       
              7 STORE_FAST               0 (f)

  3          10 LOAD_CONST               1 (2)
             13 LOAD_FAST                0 (f)
             16 LOAD_GLOBAL              2 (pos2)
             19 STORE_SUBSCR        

  4          20 LOAD_FAST                0 (f)
             23 RETURN_VALUE  

In [194]: d()
Out[194]: array([ 2.,  1.,  2.,  1.,  2.])

From the disassembled code, each time the a[pos1][pos2]=2 assignment is performed, it is indeed stored in the top of the stack but then, global (case 1) or the local (case 2) variables are returned instead. When you split the operations (case 3), the interpreter seems to all at sudden remember that it had just stored the value on the stack and does not need to reload it.

1 Comment

the function d() does not work neither... it's because you returned f = a[pos1] instead of a. If you print a it still doesn't have any 2.

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.