NumPy: create ndarray of objects

Question:

I like to create a numpy array — with a shape, say [2, 3], where each array element is a list. Yes, I know this isn’t efficient, or even desirable, and all the good reasons for that — but can it be done?

So I want a 2×3 array where each point is a length 2 vector, not a 2x3x2 array. Yes, really.

If I fudge it by making it ragged, it works:

>>> np.array([[0, 0], [0, 1], [0, 2], [1, 0], [9, 8], [2, 4, -1]], dtype=object).reshape([2, 3])
array([[list([0, 0]), list([0, 1]), list([0, 2])],
       [list([1, 0]), list([9, 8]), list([2, 4, -1])]], dtype=object)

but if numpy can make it fit cleanly, it does so, and so throws an error:

>>> np.array([[0, 0], [0, 1], [0, 2], [1, 0], [9, 8], [2, 4]], dtype=object).reshape([2, 3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: cannot reshape array of size 12 into shape (2,3)

So putting aside your instincts that this is a silly thing to want to do (it is, and I know this), can I make the last example work somehow to create a shape 2×3 array where each element is a Python list of length 2, without numpy forcing it into 2x3x2?

Asked By: xpqz

||

Answers:

You can create an empty array and fill it with objects manually:

>>> a = np.empty((3,2), dtype=object)
>>> a
array([[None, None],
       [None, None],
       [None, None]], dtype=object)
>>> a[0,0] = [1,2,3]
>>> a
array([[list([1, 2, 3]), None],
       [None, None],
       [None, None]], dtype=object)
Answered By: SomethingSomething

First, you should create an object array with expected shape.

Then, use list to fill the array.

l = [[[0, 0], [0, 1], [0, 2]], [[1, 0], [9, 8], [2, 4]]]
arr = np.empty((2, 3), dtype=object)
arr[:] = l
Answered By: 吴慈霆

Anwering my own question, based on the fine answers provided by others, here’s what I did:

l = [
    np.array([0, 0]), 
    np.array([0, 1]), 
    np.array([0, 2]), 
    np.array([1, 0]),
    np.array([9, 8]),
    np.array([2, 4])
]

arr = np.empty(len(l), dtype=object)
arr[:] = l
arr = arr.reshape((2, 3))

which gives

array([[array([0, 0]), array([0, 1]), array([0, 2])],
       [array([1, 0]), array([9, 8]), array([2, 4])]],  dtype=object)

which is exactly what I wanted. Thanks all!

Answered By: xpqz
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.