Как преобразовать NumPy (k,n,m)-размер ndarray в (k)-размер dttype=объект ndarray (n,m)-размер ndarray?

#python #arrays #numpy #object #dtype

Вопрос:

У меня есть NumPy ndarray A размером (k,n,m) int, представляющий k изображений, каждое размером nxm пикселей. Я хотел бы преобразовать его в dtype=объект ndarray B размера (k,) , содержащий каждое из отдельных изображений в виде ndarray размера (n,m).

Я могу сделать это с помощью цикла for (ниже), но есть ли более элегантный/простой способ?

 A = np.arange(2*3*4).reshape(2,3,4)

B = np.empty(A.shape[0],dtype=object)
for i in range(0,A.shape[0]):
    B[i] = A[i]

print(B)

array([array([[ 0,  1,  2,  3],
              [ 4,  5,  6,  7],
              [ 8,  9, 10, 11]]), array([[12, 13, 14, 15],
                                         [16, 17, 18, 19],
                                         [20, 21, 22, 23]])], dtype=object)
 

Комментарии:

1. B[:]=list(A) может сработать. Избежать ошибок трансляции в таком задании может быть непросто. Это может быть не быстрее, так как действие в основном одно и то же.

Ответ №1:

Ваши массивы:

 In [37]: A = np.arange(2*3*4).reshape(2,3,4)
    ...: 
    ...: B = np.empty(A.shape[0],dtype=object)
    ...: for i in range(0,A.shape[0]):
    ...:     B[i] = A[i]
    ...: 
In [38]: B
Out[38]: 
array([array([[ 0,  1,  2,  3],
              [ 4,  5,  6,  7],
              [ 8,  9, 10, 11]]), array([[12, 13, 14, 15],
                                         [16, 17, 18, 19],
                                         [20, 21, 22, 23]])], dtype=object)
 

Альтернативный способ присвоения A B . Короче, но не обязательно быстрее.

 In [39]: B[:]=list(A)
In [40]: B
Out[40]: 
array([array([[ 0,  1,  2,  3],
              [ 4,  5,  6,  7],
              [ 8,  9, 10, 11]]), array([[12, 13, 14, 15],
                                         [16, 17, 18, 19],
                                         [20, 21, 22, 23]])], dtype=object)
 

Прямое назначение не работает; это должен быть список массивов, а не массив:

 In [41]: B[:]=A
Traceback (most recent call last):
  File "<ipython-input-41-b3ca91787565>", line 1, in <module>
    B[:]=A
ValueError: could not broadcast input array from shape (2,3,4) into shape (2,)
 

Другой ответ не работает:

 In [42]: np.array([*A], dtype=object)
Out[42]: 
array([[[0, 1, 2, 3],
        [4, 5, 6, 7],
        [8, 9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]], dtype=object)
 

Комментарии:

1. видите ли вы способ сделать это с помощью конструкции np.array? возможно, указав размер dtype ?

2. Зачем бы я дал этот ответ, если бы был «лучший»? 🙁 Похоже, вы не понимаете, насколько массивы dtype объектов близки к спискам.

3. object dtype не принимает «размер». Он просто указывает указатель на объект, то же самое, что содержится в списке.

4. Спасибо! хотя объект ndarray, в отличие от списков, должен иметь форму

5. np.array не берет а shape , только а ndmin . np.array пытается создать как можно более высокий размерный массив, как показано в другом ответе. Поэтому сначала мы должны указать желаемую форму массива. np.array это функция высокого уровня, которая скрывает много логики. np.ndarray это конструктор низкого уровня, но обычно мы его не используем.

Ответ №2:

Вместо этого вы можете использовать распаковку, чтобы получить более чистый код:

 B = np.array([*A], dtype=object)
 

ИЗМЕНИТЬ: Это не работает, так как внутренние элементы также преобразуются в тип объекта.

Комментарии:

1. Вы это проверяли?

2. Да, я проверил это, результат был тот же. Я заметил опечатку, теперь я ее исправил

3. Смотрите тест в моем ответе.

4. Да, вы правы, это не работает, так как внутренние массивы также превращаются в объекты (я пропустил это). Моя ошибка, спасибо за исправление.