Mohamed Benkedadra
Mohamed Benkedadra

Reputation: 2084

Numpy concatenation of two 2D arrays while keeping data separate

I have NUMPY arrays A and B:

A = [
    [1, 2 ,3, 4, 5, 6, 7, 8, 9],
    [1, 1 ,1, 1, 5, 0, 7, 8, 3],
    ..etc
]

B = [
    [1, 2 ,3],
    [1, 0 ,1],
    ..etc
]

Both 2D arrays have the same number of lines. I would like to have create array C :

C = [
    [ [1, 2 ,3, 4, 5, 6, 7, 8, 9], [1, 2 ,3] ],
    [ [1, 1 ,1, 1, 5, 0, 7, 8, 3], [1, 0 ,1] ],
    ..etc
]

I would also like to know how i can do the opposite. meaning, go from C to A and B. I have tried functions like append, concatenate and stack. but i can't figure out how to this.

Upvotes: 0

Views: 63

Answers (3)

Rola
Rola

Reputation: 1946

I have updated my code and applied something similar to what's mentioned here:

import numpy as np
A = [
[1, 2 ,3, 4, 5, 6, 7, 8, 9],
[1, 1 ,1, 1, 5, 0, 7, 8, 3]
]

B = [
[1, 2 ,3],
[1, 0 ,1]
]

aArray=np.array(A)
bArray=np.array(B)

x_z = map(tuple,aArray)
y_z = map(tuple,bArray)
cArray=[list(i) for i in zip(x_z, y_z)]
cArray

The Output:

[[(1, 2, 3, 4, 5, 6, 7, 8, 9), (1, 2, 3)],
 [(1, 1, 1, 1, 5, 0, 7, 8, 3), (1, 0, 1)]]

Upvotes: 1

hpaulj
hpaulj

Reputation: 231395

Contrary to your description, A and B are lists

In [414]: A = [ 
     ...:     [1, 2 ,3, 4, 5, 6, 7, 8, 9], 
     ...:     [1, 1 ,1, 1, 5, 0, 7, 8, 3]]                                                             
In [415]: B = [ 
     ...:     [1, 2 ,3], 
     ...:     [1, 0 ,1]]                       

As others show, it is easy to use zip to interleave the elements of these 2 lists:

In [416]: C = [[a,b] for a,b in zip(A,B)]                                                              
In [417]: C                                                                                            
Out[417]: 
[[[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3]],
 [[1, 1, 1, 1, 5, 0, 7, 8, 3], [1, 0, 1]]]

If you want C to be an array, you need to create an object dtype array of the right size, and fill it:

In [418]: C = np.empty((2,2),object)                                                                   
In [419]: C[:,0] = A                                                                                   
In [420]: C[:,1] = B                                                                                   
In [421]: C                                                                                            
Out[421]: 
array([[list([1, 2, 3, 4, 5, 6, 7, 8, 9]), list([1, 2, 3])],
       [list([1, 1, 1, 1, 5, 0, 7, 8, 3]), list([1, 0, 1])]], dtype=object)

However if A was really an array, this assignment would not work:

In [422]: C[:,0] = np.array(A)                                                                         
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-422-d1283e1b548a> in <module>
----> 1 C[:,0] = np.array(A)

ValueError: could not broadcast input array from shape (2,9) into shape (2)

It's not impossible to assign an array A to this object C, but it's tricky.

As for the reverse

In [425]: C[:,0]                                                                                       
Out[425]: 
array([list([1, 2, 3, 4, 5, 6, 7, 8, 9]),
       list([1, 1, 1, 1, 5, 0, 7, 8, 3])], dtype=object)

A more natural way of combining arrays like A and B is:

In [424]: np.hstack((A,B))                                                                             
Out[424]: 
array([[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3],
       [1, 1, 1, 1, 5, 0, 7, 8, 3, 1, 0, 1]])

In that new array A and B loose their identity, though it's easy to recover them with indexing:

In [426]: np.hstack((A,B))[:,:-3]                                                                      
Out[426]: 
array([[1, 2, 3, 4, 5, 6, 7, 8, 9],
       [1, 1, 1, 1, 5, 0, 7, 8, 3]])

In short, your desired C is somewhat ambiguous, and not the most natural numpy structure. The original list zip is not inferior - it might even be faster.

===

Playing around with these lists, I found that

In [430]: np.array((A,B))                                                                              
Out[430]: 
array([[list([1, 2, 3, 4, 5, 6, 7, 8, 9]),
        list([1, 1, 1, 1, 5, 0, 7, 8, 3])],
       [list([1, 2, 3]), list([1, 0, 1])]], dtype=object)

This a (2,2) object array of lists. And transposing it produces the same array as in [421]:

In [431]: _.T                                                                                          
Out[431]: 
array([[list([1, 2, 3, 4, 5, 6, 7, 8, 9]), list([1, 2, 3])],
       [list([1, 1, 1, 1, 5, 0, 7, 8, 3]), list([1, 0, 1])]], dtype=object)

But trying to do the same with arrays, I hit the same error as in [422]. In fact [422] might explain this error:

In [432]: np.array((np.array(A),np.array(B)))                                                          
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-432-a4327b98cfe7> in <module>
----> 1 np.array((np.array(A),np.array(B)))

ValueError: could not broadcast input array from shape (2,9) into shape (2)

If A and B match in shape, np.array((A,B)) is a 3d array. Often when the inputs differ in shape, the result is an object dtype array. But for some combinations, such as this, it raises an error. So np.array((A,B)) is not a reliable way of making an object dtype array.

Upvotes: 1

Mark
Mark

Reputation: 92440

You can zip() them:

A = [
    [1, 2 ,3, 4, 5, 6, 7, 8, 9],
    [1, 1 ,1, 1, 5, 0, 7, 8, 3],
]

B = [
    [1, 2 ,3],
    [1, 0 ,1],
]

C = list(map(list, zip(A, B)))

C will be:

[[[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3]],
 [[1, 1, 1, 1, 5, 0, 7, 8, 3], [1, 0, 1]]]

Upvotes: 1

Related Questions