Home > Software engineering >  How to append two numpy arrays across some dimension using differently shaped arrays
How to append two numpy arrays across some dimension using differently shaped arrays

Time:05-21

I have two arrays, one of shape (4, 6, 1). I want to append the 2 values stored in another array of shape (2,) to the third dimension so that I end up with a resulting array of shape (4, 6, 3).

How do I go about this?

As an example we have:

arr1 = np.repeat(np.array([[[1], [1], [1], [1], [1], [1]]]), 4, axis=0)
arr2 = np.array([2, 3])

So we have arr1 =

arr1 = [[[1]
  [1]
  [1]
  [1]
  [1]
  [1]]

 [[1]
  [1]
  [1]
  [1]
  [1]
  [1]]

 [[1]
  [1]
  [1]
  [1]
  [1]
  [1]]

 [[1]
  [1]
  [1]
  [1]
  [1]
  [1]]]

And we want to end up with:

[[[1 2 3]
  [1 2 3]
  [1 2 3]
  [1 2 3]
  [1 2 3]
  [1 2 3]]

 [[1 2 3]
  [1 2 3]
  [1 2 3]
  [1 2 3]
  [1 2 3]
  [1 2 3]]

 [[1 2 3]
  [1 2 3]
  [1 2 3]
  [1 2 3]
  [1 2 3]
  [1 2 3]]

 [[1 2 3]
  [1 2 3]
  [1 2 3]
  [1 2 3]
  [1 2 3]
  [1 2 3]]]

Keep in mind I am generating the arrays here like this so we have an example to work off.

I have found a very convoluted way of doing it, but it feels there must be some numpy wizardry or functionality that should work.

This is what I found:

arr1 = np.repeat(np.array([[[1], [1], [1], [1], [1], [1]]]), 4, axis=0)
arr2 = np.array([2, 3])
arr2 = np.repeat(arr2, 6, axis=0)
arr2 = arr2.reshape(2, 6).T
arr2 = arr2.reshape(1, self.lag, -1)
arr2 = np.repeat(arr2, 4, axis=0)
print(arr1.shape)
print(arr2.shape)

arr3 = np.append(arr1, arr2, axis=2)
print(arr3)

We get the result we want then, but is there a better way?

CodePudding user response:

IIUC, you can broadcast the first 2 dimensions of arr2 with numpy.broadcast_to, then dstack:

np.dstack([arr1, np.broadcast_to(arr2, arr1.shape[:2] arr2.shape)])

output:

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

       [[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]],

       [[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]],

       [[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]]])

CodePudding user response:

np.tile can do the two repeats for you:

arr1 = np.repeat(np.array([[[1], [1], [1], [1], [1], [1]]]), 4, axis=0)
arr2 = np.array([2, 3])
arr2 = np.repeat(arr2, 6, axis=0)
arr2 = arr2.reshape(2, 6).T
arr2 = arr2.reshape(1, 6, -1)
arr2 = np.repeat(arr2, 4, axis=0)

arr2.shape
Out[129]: (4, 6, 2)

np.tile(np.array((2,3))[None,None,:], (4,6,1)).shape
Out[130]: (4, 6, 2)

np.concatenate((arr1,np.tile(np.array((2,3))[None,None,:], (4,6,1))), axis=2).shape
Out[132]: (4, 6, 3)

Another idea is to create the target array first, and fill it. The (2,) arr2 fills the (4,6,2) space by broadcasting (as though it were (1,1,2) shape).

res = np.zeros((4,6,3),int)
res[:,:,[0]] = arr1
res[:,:,1:] = np.array((2,3))
  • Related