Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Index an array using the colon operator in an arbitrary dimension

I have a numpy nd array. A simplified version of my task is to take a vector from along each axis. To illustrate:

import numpy
x = numpy.array(range(24)).reshape((2,3,4))
x0 = x[0,0,:]
x1 = x[0,:,0]
x2 = x[:,0,0]

However I do not necessarily know the number of dimensions x will have. So the challenge is how to place the colon : indexing operator in a variable location. An example of what such syntax could look like:

n = x.ndim
ind = list(np.zeros(n))
dim = 0
ind[dim] = ':'
y = x[ind]

or

y = indexer.index(x,ind)

for some module indexer. I could write it, but I feel like this must already be solved, I can't be the only one who wants to do this. In MATLAB, for example, you can do this with the subsref() function.

Does any such construct exist in python / numpy / other module?

like image 360
Andrew Schwartz Avatar asked Jun 26 '14 13:06

Andrew Schwartz


People also ask

What does colon do to index in Python?

A colon by itself means fetch everything. A colon on the right side of an index means everything after the specified index. A colon on the left side of an index means everything before, but not including, the index. And if we use a negative index, it means get elements from the end, going backwards.

What is the colon operator in Python?

In Python, a colon is required at the beginning of every block of code. It is easier to explain with an example. Notice how at the end of the if statement I have a colon. This tells Python that the next line of indented code should only be run IF the condition is true.

Can you index an array in Python?

Individual values stored in an array can be accessed with indexing. Where <value> is the value stored in the array, <array> is the array object name and [index] specifies the index or location of that value. In the array above, the value 6 is stored at index 2.

How do you find the index of an array element in Python?

Get the index of elements in the Python loopCreate a NumPy array and iterate over the array to compare the element in the array with the given array. If the element matches print the index.


2 Answers

As suggested from numpy's documentation about indexing you can use the slice built-in function and tuple concatenation to create variable indexes.

In fact the : in the subscript is simply the literal notation for a slice literal.

In particular : is equivalent to slice(None) (which, itself, is equivalent to slice(None, None, None) where the arguments are start, stop and step).

For example:

a[(0,) * N + (slice(None),)]

is equivalent to:

a[0, 0, ..., 0, :]   # with N zeros

The : notation for slices can only be used directly inside a subscript. For example this fails:

In [10]: a[(0,0,:)]
  File "<ipython-input-10-f41b33bd742f>", line 1
    a[(0,0,:)]
           ^
SyntaxError: invalid syntax

To allow extracting a slice from an array of arbitrary dimensions you can write a simple function such as:

def make_index(num_dimension, slice_pos):
    zeros = [0] * num_dimension
    zeros[slice_pos] = slice(None)
    return tuple(zeros)

And use it as in:

In [3]: a = np.array(range(24)).reshape((2, 3, 4))

In [4]: a[make_index(3, 2)]
Out[4]: array([0, 1, 2, 3])

In [5]: a[make_index(3, 1)]
Out[5]: array([0, 4, 8])

In [6]: a[make_index(3, 0)]
Out[6]: array([ 0, 12])

You can generalize make_index to do any kind of things. The important thing to remember is that it should, in the end, return a tuple containing either integers or slices.

like image 64
Bakuriu Avatar answered Oct 03 '22 11:10

Bakuriu


You could compose an string with the code selecting the dimension you want and use eval to execute that code string.

An start is:

n = 2
sel = "0,"*(n-1) + ":"
eval('x[' + sel + ']')

To get exactly what you want, thinks are a little bit more complicated (but not so much):

ind = 2
n = 3
sel = "".join([ ("0" if i != ind else ":") + ("," if i < n-1 else "") for i in xrange(n)])
eval('x[' + sel + ']')

It is the same strategy that is used for Dynamic SQL.

like image 22
Pablo Francisco Pérez Hidalgo Avatar answered Oct 03 '22 11:10

Pablo Francisco Pérez Hidalgo