0

I am trying to use indices stored in one set of arrays (indexPositions) to perform a simple array operation using a matrix. It is easier to explain with an example

u[(indexPositions[:,1]):(indexPositions[:,2]),(indexPositions[:,0])]=0

The object u is a big matrix whose values I want to set to zero for a given region of space. indexPositions[:,1] contains the 'lower bound' indices and indexPositions[:,2] contains the 'upper bound' indices. This reflects the fact that I want to set to zero anything in between them and therefore want to iterate between these indices.

indexPositions[:,0] contains the column index for which the aforementioned range of rows must be set to zero.

I do not understand why it is not possible to do this (I hope its clear what I'm trying to achieve). I'm sure it has something to do with python not understanding what order its supposed to do these operations in. Is there a way of specifying this? The matrix is quite huge and these operations are happening many many times so I really don't want to use a slow python loop.

chrisaycock
  • 36,470
  • 14
  • 88
  • 125
alexbcg
  • 193
  • 1
  • 1
  • 6
  • What does `indexPositions` look like? Particularly, can you paste what `indexPositions[:,1]` is? – chrisaycock May 19 '15 at 22:57
  • `indexPositions[:,1]` is an array of integers, all of which are strictly less than (component-wise) `indexPositions[:,2]` I won't copy and past the whole thing because it's quite big but an extract would be `[200 196 195 194 193 192 192 191 191 191 190 190 190 189 189 189 189 189 188 188 188 188 188 188 188 188 188 187 187 187 187 187 187 187 187 187 ...202 202 201 201 201 201 201 201 201 200 200 200 200 200 200 200 200 199]` (If you're interested each respective column for `indexPositions[:,1/2]`represent the coordinates of upper and lower surfaces of an airfoil. – alexbcg May 19 '15 at 23:03
  • I've never seen anyone use an index array *as part of* a slice. I get the same error as you if I try it manually. See http://docs.scipy.org/doc/numpy/user/basics.indexing.html#combining-index-arrays-with-slices – chrisaycock May 19 '15 at 23:07

1 Answers1

0

Just to make sure we are talking about the same thing, I'll create a simple example:

In [77]: u=np.arange(16).reshape(4,4)   
In [78]: I=np.array([[0,2,3],[1,4,2]])

In [79]: i=0
In [80]: u[I[i,0]:I[i,1],I[i,2]]
Out[80]: array([3, 7])

In [85]: i=1
In [86]: u[I[i,0]:I[i,1],I[i,2]]
Out[86]: array([ 6, 10, 14])

I'm using different column order for I, but that doesn't matter.

I selecting 2 elements from the 4th column, and 3 from the 3rd. Different lengths of results suggests that I'll have problems operation with both rows of I at once. I might have to operate on a flattened view of u.

In [93]: [u[slice(x,y),z] for x,y,z in I]
Out[93]: [array([3, 7]), array([ 6, 10, 14])]

If the lengths of the slices are all the same it's more likely that I'd be able to do all with out a loop on I rows.

I'll think about this some more, but I just want to make sure I understood the problem, and why it might be difficult.


1u[I[:,0]:I[:,1],I[:,2]] with : in the slice is defintely going to be a problem.

In [90]: slice(I[:,0],I[:,1])
Out[90]: slice(array([0, 1]), array([2, 4]), None)

Abstractly a slice object accepts arrays or lists, but the numpy indexing does not. So instead of one complex slice, you have to create 2 or more simple ones.

In [91]: [slice(x,y) for x,y in I[:,:2]]
Out[91]: [slice(0, 2, None), slice(1, 4, None)]

I've answered a similar question, one where the slice starts came from a list, but all slices had the same length. i.e. 0:3 from the 1st row, 2:5 from the 2nd, 4:7 from the 3rd etc.

Access multiple elements of an array How can I select values along an axis of an nD array with an (n-1)D array of indices of that axis?

If the slices are all the same length, then it is possible to use broadcasting to construct the indexing arrays. But in the end the indexing will still be with arrays, not slices.


Fast slicing of numpy array multiple times Numpy Array Slicing deal with taking multiple slices from a 1d array, slices with differing offsets and lengths. Your problem could, I think, be cast that way. The alterantives considered all require a list comprehension to construct the slice indexes. The indexes can then be concatenated, followed by one indexing operation, or alteratively, index multiple times and concanentate the results. Timings vary with the number and length of the slices.

An example, adapted from those earlier questions, of constructing a flat index list is:

In [130]: il=[np.arange(v[0],v[1])+v[2]*u.T.shape[1] for v in I]
# [array([12, 13]), array([ 9, 10, 11])]
In [132]: u.T.flat[np.concatenate(il)]
# array([ 3,  7,  6, 10, 14])

Same values as my earlier examples, but in 1 list, not 2.

If the slice arrays have same length, then we can get back an array

In [145]: I2
Out[145]: 
array([[0, 2, 3],
       [1, 3, 2]])
In [146]: il=np.array([np.arange(v[0],v[1]) for v in I2])
In [147]: u[il,I2[:,2]]
Out[147]: 
    array([[ 3,  6],
           [ 7, 10]])

In this case, il = I2[:,[0]]+np.arange(2) could be used to construct the 1st indexing array instead of the list comprehension (this is the broadcasting I mentioned earlier).

Community
  • 1
  • 1
hpaulj
  • 221,503
  • 14
  • 230
  • 353