Конкатенация массивов 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