Home > Software engineering >  Python numpy array of numpy arrays as object
Python numpy array of numpy arrays as object

Time:12-28

I have some np arrays. I want to concatenate them as objects in an np array.

 coords1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
 coords2 = np.array([[13, 14, 15, 16], [17, 18, 19, 20]])

I want to obtain coordsAll

 coordsAll = [[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]],
             [[13, 14, 15, 16], [17, 18, 19, 20]]]

This is my code:

 coords1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
 coords2 = np.array([[13, 14, 15, 16], [17, 18, 19, 20]])
 coordsAll = np.empty(np.array(np.array((0, 4), int)), object)
 coordsAll = np.append (coordsAll, coords1, axis=0)
 coordsAll = np.append(coordsAll, coords2, axis=0)

coordsAll is now

 [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20]]

but i want two objects in my output array like

 [[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], [[13, 14, 15, 16], [17, 18, 19, 20]]]

Many thanks.

CodePudding user response:

Maybe something like that:

coordsAll = np.array([coords2, coords1], dtype=object)
print(coordsAll)
print(coordsAll.dtype)

CodePudding user response:

In [457]: coordsAll
Out[457]: 
array([[1, 2, 3, 4],
       [5, 6, 7, 8],
       [9, 10, 11, 12],
       [13, 14, 15, 16],
       [17, 18, 19, 20]], dtype=object)

Your repeated use of np.append joins a (0,4) and (3,4) to make a (3,4), and then adds a (2,4), resulting in a (5,4). Specifying object dtype doesn't change that behavior. You might as well do:

In [458]: np.concatenate((coords1, coords2), axis=0)
Out[458]: 
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16],
       [17, 18, 19, 20]])

Where concatenate takes a whole list of arrays. Repeated calls in a loop is inefficient. Plus you have to make that weird (0,4) array to start with. Modeling array operations on list ones is not a good idea.

The safest way to make an object array of a desired size, is to initial it, and then fill:

In [459]: res = np.empty(2, object)
In [460]: res
Out[460]: array([None, None], dtype=object)
In [461]: res[0] = coords1
In [462]: res[1] = coords2
In [463]: res
Out[463]: 
array([array([[ 1,  2,  3,  4],
              [ 5,  6,  7,  8],
              [ 9, 10, 11, 12]]), array([[13, 14, 15, 16],
                                         [17, 18, 19, 20]])], dtype=object)

np.array with object dtype also works in this case, but may fail with other combinations of shapes:

In [464]: np.array((coords1, coords2), object)
Out[464]: 
array([array([[ 1,  2,  3,  4],
              [ 5,  6,  7,  8],
              [ 9, 10, 11, 12]]), array([[13, 14, 15, 16],
                                         [17, 18, 19, 20]])], dtype=object)

arrays of the same shape produces a 3d array:

In [465]: np.array((coords1, coords1), object)
Out[465]: 
array([[[1, 2, 3, 4],
        [5, 6, 7, 8],
        [9, 10, 11, 12]],

       [[1, 2, 3, 4],
        [5, 6, 7, 8],
        [9, 10, 11, 12]]], dtype=object)

and (4,3) with (4,2) produces an error:

In [466]: np.array((coords1.T, coords2.T), object)
Traceback (most recent call last):
  File "<ipython-input-466-dff6d2a13fa4>", line 1, in <module>
    np.array((coords1.T, coords2.T), object)
ValueError: could not broadcast input array from shape (4,3) into shape (4,)

Keep in mind that your desired array is not a "normal" ndarray. It's much closer to the simple list [coords1, coords2], with few of multidimensional advantages of Out[458].

  • Related