gustavgans
gustavgans

Reputation: 5191

Append 2 dimensional arrays to one single array

I have a loop over 2-dimensional np.arrays() and I need to add these arrays to one single array.

in plain Python I would do this

In [37]: a1 = [[1,2],[3,4]]

In [38]: b1 = [[5,6],[7,8]]

In [39]: l1 = []

In [40]: l1.append(a1)

In [41]: l1.append(b1)

In [42]: l1
Out[42]: [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]

How do I get the same result with numpy for l1?

Upvotes: 4

Views: 327

Answers (3)

Alex Riley
Alex Riley

Reputation: 176740

Here is one way to produce that output from the arrays:

>>> np.dstack((a1,b1)).transpose(2,0,1)

array([[[ 1,  2],
        [ 3,  4]],

       [[ 5,  6],
        [ 7,  8]],

np.dstack produces a 3D array, but the axes need to read in a different order. We want the order of the axes (0, 1, 2) changed to (2, 0, 1), hence the need to transpose and swap the axes.


Below is potentially useful - but not immediately relevant - information about concatenating arrays. (Typed before my misinterpretation of the question was pointed out.)

One way to join arrays is to use np.concatenate:

>>> np.concatenate((a1, b1))
array([[1, 2],
       [3, 4],
       [5, 6],
       [7, 8]])

This stacks one below the other. You can also concatenate the arrays side-by-side with np.concatenate((a1, b1), axis=1). (More than two arrays can be passed into the function.)

There are other functions to do this; the two operations above can be done with np.vstack((a1,b1)) and np.hstack((a1,b1)) respectively.

If you want to join in the arrays in a 3D array, you can use np.dstack((a1,b1)):

array([[[1, 5],
        [2, 6]],

       [[3, 7],
        [4, 8]]])

Keep in mind that Numpy arrays, unlike Python lists, cannot grow in memory dynamically. These operations cause the arrays to be copied and a new block of memory to be filled with the bigger array. This can be inefficient if the arrays are large.

Upvotes: 3

gg349
gg349

Reputation: 22671

Just use:

l1 = np.array([a1,b1])

Notice also that in numpy you don't append to arrays. You allocate them first, and then you fill them:

import numpy as np
a1 = np.array([[1,2],[3,4]])
b1 = np.array([[5,6],[7,8]])
#allocate exact size of the final array
l1 = empty(((2,)+a1.shape),dtype=a1.dtype)
l1[0]=a1
l1[1]=b1

or you use one of the many helper functions (dstack,hstack,concatenate described by the others)

EDIT: I find both solutions above very readable and close to python lists syntax, but this is rather subjective. Timing how fast this is, you find that both solutions are marginally faster to the fastest solution proposed by @unutbu, based on concatenate. Notice moreover that this does not create a view.

Upvotes: 4

unutbu
unutbu

Reputation: 879123

a1 = np.array([[1,2],[3,4]])
b1 = np.array([[5,6],[7,8]])
l1 = np.r_['0,3', a1, b1]

yields

array([[[1, 2],
        [3, 4]],

       [[5, 6],
        [7, 8]]])

The special directive '0,3' tells np.r_ to concatenate along axis=0, and produce a result with at least 3 dimensions.


Or, alternatively, using concatenate and reshape is more readable and faster:

l1 = np.concatenate([a1, b1]).reshape((2,)+a1.shape))

In [111]: a2 = np.tile(a1, (10000,1))

In [112]: b2 = np.tile(b1, (10000,1))

In [113]: %timeit np.r_['0,3', a2, b2].shape
10000 loops, best of 3: 62.4 µs per loop

In [114]: %timeit np.concatenate([a2, b2]).reshape((2,)+a2.shape)
10000 loops, best of 3: 39.8 µs per loop

Upvotes: 3

Related Questions