In [13]: arr1 = np.array(['a', 'b', 'c', 'd', 'e', 'f']).reshape(2, 3)
...: arr2 = np.array(['g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p']).reshape(2, 5)
...: arr3 = np.array(['r', 's', 't', 'u']).reshape(2, 2)
Если я пытаюсь создать массив dtype объекта из этих массивов, я получаю ошибку:
In [22]: np.array([arr1, arr2, arr3])
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-22-155b98609c5b> in <module>
----> 1 np.array([arr1, arr2, arr3])
ValueError: could not broadcast input array from shape (2,3) into shape (2)
Если они отличаются по количеству строк, это будет работать, но с общей строкой Номер результата - ошибка. В таком случае я обычно рекомендую определить массив объектов правильного размера и заполнить его следующим образом:
In [14]: arr = np.empty((2,3), object)
In [15]: arr
Out[15]:
array([[None, None, None],
[None, None, None]], dtype=object)
Но если я пытаюсь назначить первый столбец, я получаю ту же ошибку:
In [17]: arr[:,0] = arr1
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-17-9894797aa09e> in <module>
----> 1 arr[:,0] = arr1
ValueError: could not broadcast input array from shape (2,3) into shape (2)
Вместо этого я могу назначить строку за строкой:
In [18]: arr[0,0] = arr1[0]
In [19]: arr[1,0] = arr1[1]
In [20]: arr[0,1] = arr2[0]
...
In [21]: arr
Out[21]:
array([[array(['a', 'b', 'c'], dtype='<U1'),
array(['g', 'h', 'i', 'j', 'k'], dtype='<U1'), None],
[array(['d', 'e', 'f'], dtype='<U1'), None, None]], dtype=object)
В качестве альтернативы, мы можем назначить вложенные списки столбцам без ошибки трансляции. Это фактически то, что делает принятый ответ:
In [23]: arr[:,0] = arr1.tolist()
In [24]: arr[:,1] = arr2.tolist()
In [25]: arr[:,2] = arr3.tolist()
In [26]: arr
Out[26]:
array([[list(['a', 'b', 'c']), list(['g', 'h', 'i', 'j', 'k']),
list(['r', 's'])],
[list(['d', 'e', 'f']), list(['l', 'm', 'n', 'o', 'p']),
list(['t', 'u'])]], dtype=object)
Эти трудности в создании желаемого массива являются хорошим индикатором того, что это НЕ, НЕ, хорошая структура массива numpy
. Если это трудно сделать, то, вероятно, также будет трудно использовать или, по крайней мере, медленно. Итерация в массиве dtype объекта выполняется медленнее, чем итерация в списке. Его единственное преимущество по сравнению со списком состоит в том, что его легко изменить.
====
np.array
действительно работает, если входными данными являются списки, а не массив:
In [33]: np.array([arr1.tolist(), arr2.tolist(), arr3.tolist()])
Out[33]:
array([[list(['a', 'b', 'c']), list(['d', 'e', 'f'])],
[list(['g', 'h', 'i', 'j', 'k']), list(['l', 'm', 'n', 'o', 'p'])],
[list(['r', 's']), list(['t', 'u'])]], dtype=object)
или преобразовать в список, чтобы получить более «чистое» отображение:
In [34]: _.tolist()
Out[34]:
[[['a', 'b', 'c'], ['d', 'e', 'f']],
[['g', 'h', 'i', 'j', 'k'], ['l', 'm', 'n', 'o', 'p']],
[['r', 's'], ['t', 'u']]]
, а транспонирование этого массива дает желаемый (3,2) массив:
In [35]: _33.T.tolist()
Out[35]:
[[['a', 'b', 'c'], ['g', 'h', 'i', 'j', 'k'], ['r', 's']],
[['d', 'e', 'f'], ['l', 'm', 'n', 'o', 'p'], ['t', 'u']]]