Johnny S
Johnny S

Reputation: 11

Creating Numpy-Arrays without iterating in Python

Say I have a numpy array with shape (2,3) filled with floats.

I also need an array of all possible combinations of X and Y Values (their corresponding position in the array). Is there something like a simpe function to get the indices as a tuple from a numpy array in which I don't need to have for-loops iterate through the array?

Example Code:

arr=np.array([np.array([1.0,1.1,1.2]),
              np.array([1.0,1.1,1.2])])
indices=np.zeros([arr.shape[0]*arr.shape[1]])

#I want an array of length 6 like np.array([[0,0],[0,1],[0,2],[1,0],[1,1], [1,2]])
#Code so far, iterates though :(
ik=0
for i in np.arange(array.shape[0]):
    for k in np.arange(array.shape[1]):
        indices[ik]=np.array([i,k])
        ik+=1

Now after this, I want to also make an array with the length of the 'indices' array containing "XYZ coordinates" as in each element containing the XY 'indices' and a Z Value from 'arr'. Is there an easier way (and if possible without iterating through the arrays again) than this:

xyz=np.zeros(indices.shape[0])
for i in range(indices.shape[0]):
    xyz=np.array([indices[i,0],indices[i,1],arr[indices[i,0],indices[i,1]]

Upvotes: 1

Views: 124

Answers (3)

plonser
plonser

Reputation: 3363

There are probably many ways to achieve this ... A possible solution is the following.

The first problem can be solved using np.unravel_index

max_it = arr.shape[0]*arr.shape[1]
indices = np.vstack(np.unravel_index(np.arange(max_it),arr.shape)).T

The second array can then be constructed with

xyz = np.column_stack((indices,arr[indices[:,0],indices[:,1]]))

Timings

On your array timeit gives for my code 10000 loops, best of 3: 27.7 µs per loop (grc's solution needs 10000 loops, best of 3: 39.6 µs per loop)

On larger arrays with shape=(50,60) I have 1000 loops, best of 3: 247 µs per loop (grc's solution needs 100 loops, best of 3: 2.17 ms per loop)

Upvotes: 0

grc
grc

Reputation: 23545

You can use np.ndindex:

indices = np.ndindex(arr.shape)

This will give an iterator rather than an array, but you can easily convert it to a list:

>>> list(indices)
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]

Then you can stack the indices with the original array along the 2nd dimension:

np.hstack((list(indices), arr.reshape((arr.size, 1))))

Upvotes: 2

Pierre de Buyl
Pierre de Buyl

Reputation: 7293

For your indices:

indices = np.concatenate((np.meshgrid(range(arr.shape[0]), range(arr.shape[1])))

Upvotes: 0

Related Questions