1

I have a 4d array x, for which I want to loop through the first axis, modify that 3d array, and add this modified array to a new 4d array y.

I am currently doing something like:

xmod = modify(x[0, :, :, :])
y = xmod.reshape(1, x.shape[1], x.shape[2], x.shape[3])
for i in range(1, x.shape[0]):
    xmod = modify(x[i, :, :, :])
    y = np.vstack((y, xmod))

I am guessing there is amuch cleaner to do this. How?

3
  • Python-level loops, and especially appending in a loop, are spectacularly slow ways to use NumPy. Can you make modify operate in a vectorized manner on all of x? Commented Nov 19, 2015 at 22:50
  • I would love to, but I don't know if I can. My modify is really the resizing of an image: xmod = scipy.misc.imresize(x[i,:,:,0], 1.3). I don't think imresize can be vectorized, but maybe I'm wrong? Commented Nov 19, 2015 at 22:54
  • Your best bet is probably to create a blank array of the appropriate final size and then slice-assign the results into it one by one. Commented Nov 19, 2015 at 23:00

1 Answer 1

2

If you must act on x one submatrix at a time you could do:

y = np.zeros_like(x)
for i in range(x.shape[0]):
    y[i,...] = modify(x[i,...])

e.g.

In [595]: x=np.arange(24).reshape(4,3,2)
In [596]: y=np.zeros_like(x)
In [597]: for i in range(x.shape[0]):
   .....:     y[i,...]=x[i,...]*2
   .....:     
In [598]: y
Out[598]: 
array([[[ 0,  2],
        [ 4,  6],
        ...
        [40, 42],
        [44, 46]]])

appending to lists is generally better than repeatedly 'appending' to arrays:

In [599]: y=[]
In [600]: for row in x:
   .....:     y.append(row*2)
   .....: 
In [601]: y=np.array(y)

for very large cases you could see if vstack (or concatenate axis=0) is faster. But you have to explicitly add a beginning dimension to the arrays.

In [615]: y=[]
In [616]: for row in x:
    y.append((row*2)[None,:])
   .....:     
In [617]: np.vstack(y)
Sign up to request clarification or add additional context in comments.

2 Comments

for subarray in x and np.empty_like would be faster.
In my first example I'd have to use for i,row in enumerate(x):, or may zip(x,y). In a situation like this I doubt if empty_like is that much faster than zeros_like. The iteration takes much more time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.