Конкатенация массивов Numpy без копирования

В Numpy я могу объединить два массива от конца до конца с помощью np.append или np.concatenate:

>>> X = np.array([[1,2,3]])
>>> Y = np.array([[-1,-2,-3],[4,5,6]])
>>> Z = np.append(X, Y, axis=0)
>>> Z
array([[ 1,  2,  3],
       [-1, -2, -3],
       [ 4,  5,  6]])

Но они делают копии своих входных массивов:

>>> Z[0,:] = 0
>>> Z
array([[ 0,  0,  0],
       [-1, -2, -3],
       [ 4,  5,  6]])
>>> X
array([[1, 2, 3]])

Есть ли способ объединить два массива в представление, то есть без копирования? Для этого потребуется подкласс np.ndarray?

Ответ 1

Память, принадлежащая массиву Numpy, должна быть смежной. Если вы выделили массивы отдельно, они случайным образом разбросаны по памяти, и нет возможности представить их в виде массива Numpy.

Если вы заранее знаете, сколько массивов вам нужно, вы можете вместо этого начать с одного большого массива, который вы заранее выделите, и пусть каждый из небольших массивов будет представлять собой большой массив (например, полученный путем нарезки).

Ответ 2

Просто инициализируйте массив, прежде чем заполнять его данными. Если вы хотите, вы можете выделить больше места, чем нужно, и он не займет больше ОЗУ из-за работы numpy.

A = np.zeros(R,C)
A[row] = [data]

Память используется только один раз, когда данные помещаются в массив. Создание нового массива из конкатенации двух никогда не будет завершено в наборе данных любого размера, то есть в наборе данных > 1 ГБ или около того.

Ответ 3

Не совсем элегантный, но вы можете приблизиться к тому, что хотите, используя кортеж для хранения указателей на массивы. Теперь я понятия не имею, как я буду использовать его в этом случае, но раньше я делал такие вещи.

>>> X = np.array([[1,2,3]])
>>> Y = np.array([[-1,-2,-3],[4,5,6]])
>>> z = (X, Y)
>>> z[0][:] = 0
>>> z
(array([[0, 0, 0]]), array([[-1, -2, -3],
       [ 4,  5,  6]]))
>>> X
array([[0, 0, 0]])

Ответ 4

Вы можете создать массив массивов, например:

>>> from numpy import *
>>> a = array([1.0, 2.0, 3.0])
>>> b = array([4.0, 5.0])
>>> c = array([a, b])
>>> c
array([[ 1.  2.  3.], [ 4.  5.]], dtype=object)
>>> a[0] = 100.0
>>> a
array([ 100.,    2.,    3.])
>>> c
array([[ 100.    2.    3.], [ 4.  5.]], dtype=object)
>>> c[0][1] = 200.0
>>> a
array([ 100.,  200.,    3.])
>>> c
array([[ 100.  200.    3.], [ 4.  5.]], dtype=object)
>>> c *= 1000
>>> c
array([[ 100000.  200000.    3000.], [ 4000.  5000.]], dtype=object)
>>> a
array([ 100.,  200.,    3.])
>>> # Oops! Copies were made...

Проблема заключается в том, что он создает копии в широковещательных операциях (звучит как ошибка).

Ответ 5

Ответ основан на моем другом ответе в Ссылка на ndarray строки в ndarray

X = np.array([[1,2,3]])
Y = np.array([[-1,-2,-3],[4,5,6]])
Z = np.array([None, None, None])
Z[0] = X[0]
Z[1] = Y[0]
Z[2] = Y[1]

Z[0][0] = 5 # X would be changed as well

print(X)
Output: 
array([[5, 2, 3]])

# Let make it a function!
def concat(X, Y, copy=True):
    """Return an array of references if copy=False""" 
    if copy is True:  # deep copy
        return np.append(X, Y, axis=0)
    len_x, len_y = len(X), len(Y)
    ret = np.array([None for _ in range(len_x + len_y)])
    for i in range(len_x):
        ret[i] = X[i]
    for j in range(len_y):
        ret[len_x + j] = Y[j] 
    return ret