Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot assign values to a 'double slice' using numpy

How would I do the following in numpy?

  1. select all rows of an array containing note more than 50% 0 values.
  2. select first n (let's say 2) rows from all rows satisfying 1.
  3. do something and place modified rows on same index of a zero array with equal shape of 1.

The following results in an array where no new values are assigned:

In [177]:    
a = np.array([[0,0,3],[4,5,6],[7,0,0],[10,11,12],[13,14,15]])
b = np.zeros_like(a)
a
Out[177]:    
array([[ 0,  0,  3],
       [ 4,  5,  6],
       [ 7,  0,  0],
       [10, 11, 12],
       [13, 14, 15]])

In [178]:
# select all rows containg note more than 50% 0 values
percent = np.sum(a == 0, axis=-1) / float(check.shape[1])
percent = percent >= 0.5
slice = np.invert(percent).nonzero()[0]

In [183]:
# select first two rows satisfying 'slice'
a[slice][0:2] 

Out[183]:    
array([[ 4,  5,  6],
       [10, 11, 12]])

In [182]:
# do something and place modified rows on same index of zero array
b[slice][0:2] = a[slice][0:2] * 2

In [184]:
b
Out[184]:    
array([[0, 0, 0],
       [0, 0, 0],
       [0, 0, 0],
       [0, 0, 0],
       [0, 0, 0]])
like image 540
Mattijn Avatar asked Jan 13 '16 10:01

Mattijn


1 Answers

The problem is that b[slice] creates a copy rather than a view (it triggers fancy indexing). The code b[slice][0:2] creates a view of this copy (not the original b!). Therefore...

b[slice][0:2] = a[slice][0:2] * 2

...is assigning the corresponding rows of a to a view of the copy of b.

Because it can lead to these situations, it's better not to chain indexing operations in this way. Instead, just compute the relevant row numbers for slice first and then do the assignment:

slice = np.invert(percent).nonzero()[0][:2] # first two rows
b[slice] = a[slice] * 2
like image 68
Alex Riley Avatar answered Sep 19 '22 00:09

Alex Riley