Как я могу добавить многомерный массив к новому измерению с Numpy? - PullRequest
0 голосов
/ 25 марта 2020

У меня есть пустой список: x = [].

У меня есть массив numpy, y, формы: (180, 161). Я не могу обязательно определить x как np.empty определенной формы, потому что я не буду знать форму y раньше времени.

Я хочу добавить y к x так что x будет иметь .shape (1, 180, 161).

Тогда, если я добавлю больше, я хочу, чтобы это было (n, 180, 161)

Я пытался .append и .stack, но у меня было множество ошибок:

TypeError: only size-1 arrays can be converted to Python scalars
ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 3 dimension(s) and the array at index 1 has 2 dimension(s)

И так далее. Кажется, это должно быть просто, но это странно сложно.

Ответы [ 3 ]

1 голос
/ 25 марта 2020

Если вы сохраните x как list, то, если вы просто хотите сохранить форму, добавив, это возможно:

>>> import numpy as np

>>> x = []

>>> y = np.arange(12).reshape(3,4)

>>> x.append(y)

>>> np.shape(x)
(1, 3, 4)

>>> x.append(y)

>>> np.shape(x)
(2, 3, 4)

>>> for i in range(10):
...     x.append(y)


>>> np.shape(x)
(12, 3, 4)

Но, учитывая, что вы имеете дело с np.array s, это может быть вам неудобно сохранять x как list, поэтому вы можете попробовать это:

>>> x = np.array(x)

>>> x.shape
(12, 3, 4)


>>> y[None,...].shape
(1, 3, 4)

>>> np.append(x, y[None,...],axis=0).shape
(13, 3, 4)

Слово предостережения: Как указано @ hpaulj :

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

x = np.array([*x, y])

Правильное использование будет:

x = np.concatenate([x, y[None,...]], axis=0)

В любом случае, объединение или добавление - это, как правило, увеличение скорости в numpy. Поэтому, если вам абсолютно не нужно создавать массив таким образом, вы должны работать со списками. Также большинство функций, примененных к np.arrays, работают и на list s. Обратите внимание, что функции применяются к массивам, а не к методам объекта np.array. Например:

>>> x = list((1, 2, 3, 4))
>>> np.shape(x)
(4,)
>>> x.shape
Traceback (most recent call last):

  File "<ipython-input-100-9f2b259887ef>", line 1, in <module>
    x.shape

AttributeError: 'list' object has no attribute 'shape'

Поэтому я бы предложил добавить список, а затем, после того как вы закончили добавлять все массивы, преобразовать список в np.array, если вам требуется.

1 голос
/ 25 марта 2020

Предполагая, что все элементы в x имеют одинаковую форму, вы можете сначала создать list, а затем либо создать массив NumPy из списка.

Там у вас есть два варианта:

  • np.array(), что быстрее, но не гибко
  • np.stack(), что медленнее, но позволяет выбрать, по какой оси должен происходить стек (это примерно эквивалентно np.array().transpose(...).copy()

Код будет выглядеть так:

import numpy as np


n = 100
x = [np.random.randint(0, 10, (10, 20)) for _ in range(n)]

# same as: y = np.stack(x, 0)
y = np.array(x)

print(y.shape)
# (100, 10, 20)

Конечно, эту строку:

x = [np.random.randint(0, 10, (10, 20)) for _ in range(n)]

можно заменить с:

x = []
for _ in range(n):
    x.append(np.random.randint(0, 10, (10, 20)))

Вы также можете использовать np.append(), например:

def stacker(arrs):
    result = arrs[0][None, ...]
    for arr in arrs[1:]:
        result = np.append(result, arr[None, ...], 0)
    return result

, но с характеристиками horrifi c:

n = 1000
shape = (100, 100)
x = [np.random.randint(0, n, shape) for _ in range(n)]

%timeit np.array(x)
# 10 loops, best of 3: 21.1 ms per loop
%timeit np.stack(x)
# 10 loops, best of 3: 21.6 ms per loop
%timeit stacker(x)
# 1 loop, best of 3: 11 s per loop

и, как вы можете видеть, с точки зрения производительности, метод list работает намного быстрее.

1 голос
/ 25 марта 2020

Вы можете изменить y на (1, *y.shape).

Тогда для добавления массива вы можете сказать: y_1 = np.vstack((y, new_arr))

, где y_1.shape создает массив (2, *y.shape) numpy. Чтобы сохранить память, вы можете сказать y = np.vstack((y, new_arr))

Однако, возможно, вам придется изменить форму массива на (1, *y.shape).

Это очень простой пример c:

import numpy as np

a = np.ones((1,2,3))
b = np.ones((1,2,3))
np.vstack((a,b)).shape # (2,2,3)

Дайте мне знать, если это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...