Numpyでは、np.append
またはnp.concatenate
で2つの配列をエンドツーエンドで連結できます。
>>> 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]])
2つの配列をviewに連結する方法、つまりコピーせずに方法はありますか? np.ndarray
サブクラスが必要ですか?
Numpy配列に属するメモリは連続している必要があります。配列を個別に割り当てた場合、それらはメモリ内にランダムに散在し、ビューNumpy配列としてそれらを表す方法はありません。
必要な配列の数が事前にわかっている場合は、代わりに、事前に割り当てた1つの大きな配列から開始し、小さな配列のそれぞれを大きな配列のビューにすることができます(たとえば、スライスによって取得されます)。
データを入力する前に配列を初期化するだけです。必要に応じて、必要以上のスペースを割り当てることができ、numpyの動作方法により、それ以上RAMを占有しません。
A = np.zeros(R,C)
A[row] = [data]
メモリは、データが配列に配置されると使用されます。 2つの連結から新しい配列を作成しても、任意のサイズのデータセット、つまり1GB以上のデータセットでは終了しません。
まったくエレガントではありませんが、配列へのポインタを格納するためにタプルを使用して、望みに近づけることができます。今、私はこのケースでそれをどのように使用するか分かりませんが、以前にこのようなことをしました。
>>> 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]])
私は同じ問題を抱えていましたが、通常は(コピーで)連結した後、元の配列を再割り当てして連結したもののビューになりました:
import numpy as np
def concat_no_copy(arrays):
""" Concats the arrays and returns the concatenated array
in addition to the original arrays as views of the concatenated one.
Parameters:
-----------
arrays: list
the list of arrays to concatenate
"""
con = np.concatenate(arrays)
viewarrays = []
for i, arr in enumerate(arrays):
arrnew = con[sum(len(a) for a in arrays[:i]):
sum(len(a) for a in arrays[:i + 1])]
viewarrays.append(arrnew)
assert all(arr == arrnew)
# return the view arrays, replace the old ones with these
return con, viewarrays
次のようにテストできます。
def test_concat_no_copy():
arr1 = np.array([0, 1, 2, 3, 4])
arr2 = np.array([5, 6, 7, 8, 9])
arr3 = np.array([10, 11, 12, 13, 14])
arraylist = [arr1, arr2, arr3]
con, newarraylist = concat_no_copy(arraylist)
assert all(con == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14]))
for old, new in Zip(arraylist, newarraylist):
assert all(old == new)
答えは 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's 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
次のような配列の配列を作成できます。
>>> 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...
問題は、ブロードキャスト操作でコピーを作成することです(バグのように聞こえます)。