I find myself needing to create a numpy array of dtype="object" whose elements are themselves numpy arrays. I can manage to do this if the arrays are different lengths:
arr_of_arrs = np.empty((2,2), dtype=np.object)
arr_list = [np.arange(i) for i in range(4)]
arr_of_arrs.flat[:] = arr_list
print(arr_of_arrs)
array([[array([], dtype=int32), array([0])],
[array([0, 1]), array([0, 1, 2])]], dtype=object)
But if they happen to be the same length, it doesn't work and I am not entirely sure how it is generating the values it gives me:
arr_list = [np.arange(2) for i in range(4)]
arr_of_arrs.flat[:] = arr_list
print(arr_of_arrs)
[[0 1]
[0 1]]
Is this even doable? numpy seems to try and coerce the data into "making sense" despite my best efforts to prevent it from doing so...
1 Answer 1
If the array is 1d, the assignment works fine:
In [767]: arr = np.empty(4,object)
In [768]: arr[:] = [np.arange(6) for _ in range(4)]
In [769]: arr
Out[769]:
array([array([0, 1, 2, 3, 4, 5]), array([0, 1, 2, 3, 4, 5]),
array([0, 1, 2, 3, 4, 5]), array([0, 1, 2, 3, 4, 5])], dtype=object)
In [770]: arr.reshape(2,2)
Out[770]:
array([[array([0, 1, 2, 3, 4, 5]), array([0, 1, 2, 3, 4, 5])],
[array([0, 1, 2, 3, 4, 5]), array([0, 1, 2, 3, 4, 5])]],
dtype=object)
We can also start with (2,2), but assign to ravel()
(a view
):
In [771]: arr = np.empty((2,2),object)
In [772]: arr.ravel()[:] = [np.arange(6) for _ in range(4)]
In [773]: arr
Out[773]:
array([[array([0, 1, 2, 3, 4, 5]), array([0, 1, 2, 3, 4, 5])],
[array([0, 1, 2, 3, 4, 5]), array([0, 1, 2, 3, 4, 5])]],
dtype=object)
flat
apparently serializes the RHS:
In [774]: arr.flat = [np.arange(6) for _ in range(4)]
In [775]: arr
Out[775]:
array([[0, 1],
[2, 3]], dtype=object)
If the RHS list is nested right we can assign directly to the 2d array:
In [779]: alist = Out[770].tolist()
In [780]: alist # list of lists of arrays
Out[780]:
[[array([0, 1, 2, 3, 4, 5]), array([0, 1, 2, 3, 4, 5])],
[array([0, 1, 2, 3, 4, 5]), array([0, 1, 2, 3, 4, 5])]]
In [781]: arr = np.empty((2,2),object)
In [782]: arr[:] = alist
In [783]: arr
Out[783]:
array([[array([0, 1, 2, 3, 4, 5]), array([0, 1, 2, 3, 4, 5])],
[array([0, 1, 2, 3, 4, 5]), array([0, 1, 2, 3, 4, 5])]],
dtype=object)
arr_of_arrs
starts as a 1d array, e.g.np.empty(4, object)
. You can reshape it later if needed.flat
is flattening and iterating both sides, which messes up this assignment.arr_of_arrays.ravel()[:]=...
also works better.