Get indices for all elements in an array in numpy
Asked Answered
A

3

7

I'm trying to get a list of the indices for all the elements in an array so for an array of 1000 x 1000 I end up with [(0,0), (0,1),...,(999,999)].

I made a function to do this which is below:

def indices(alist):
    results = []
    ele = alist.size
    counterx = 0
    countery = 0
    x = alist.shape[0]
    y = alist.shape[1]
    while counterx < x:
        while countery < y:
            results.append((counterx,countery))
            countery += 1
        counterx += 1
        countery = 0
    return results

After I timed it, it seemed quite slow as it was taking about 650 ms to run (granted on a slow laptop). So, figuring that numpy must have a way to do this faster than my mediocre coding, I took a look at the documentation and tried:

indices = [k for k in numpy.ndindex(q.shape)]
which took about 4.5 SECONDS (wtf?)
indices = [x for x,i in numpy.ndenumerate(q)]
better, but 1.5 seconds!

Is there a faster way to do this?

Thanks

Acquah answered 28/6, 2013 at 20:3 Comment(0)
A
3

Ahha!

Using numpy to build an array of all combinations of two arrays

Runs in 41 ms as opposed to the 330ms using the itertool.product one!

Acquah answered 29/6, 2013 at 20:51 Comment(0)
B
11

how about np.ndindex?

np.ndindex(1000,1000)

This returns an iterable object:

>>> ix = numpy.ndindex(1000,1000)
>>> next(ix)
(0, 0)
>>> next(ix)
(0, 1)
>>> next(ix)
(0, 2)

In general, if you have an array, you can build the index iterable via:

index_iterable = np.ndindex(*arr.shape)

Of course, there's always np.ndenumerate as well which could be implemented like this:

def ndenumerate(arr):
    for ix in np.ndindex(*arr.shape):
        yield ix,arr[ix]
Bookkeeping answered 28/6, 2013 at 20:14 Comment(1)
Out of idle curiosity, how do the timings for these compare to the timings made by the OP?Josselyn
E
4

Have you thought of using itertools? It will generate an iterator for your results, and will almost certainly be optimally fast:

import itertools

a = range(1000)
b = range(1000)

product = itertools.product(a, b)

for x in product:
    print x

# (0, 0)
# (0, 1)
# ...
# (999, 999)

Notice this didn't require the dependency on numpy. Also, notice the fun use of range to create a list from 0 to 999.

Equities answered 28/6, 2013 at 20:12 Comment(2)
good answer assuming it is a true 2d array and not a list of variably sized list (+1)Paestum
Ah, hmm. Yes. Well, I answered the question the OP asked. I can expand if the question is more general.Equities
A
3

Ahha!

Using numpy to build an array of all combinations of two arrays

Runs in 41 ms as opposed to the 330ms using the itertool.product one!

Acquah answered 29/6, 2013 at 20:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.