空のnumpy配列に新しい行を追加する方法


158

標準のPython配列を使用して、次のことができます。

arr = []
arr.append([1,2,3])
arr.append([4,5,6])
# arr is now [[1,2,3],[4,5,6]]

しかし、私はnumpyで同じことをすることはできません。例えば:

arr = np.array([])
arr = np.append(arr, np.array([1,2,3]))
arr = np.append(arr, np.array([4,5,6]))
# arr is now [1,2,3,4,5,6]

私も調べましたvstackvstack、空の配列で使用すると、次のようになります。

ValueError: all the input array dimensions except for the concatenation axis must match exactly

では、numpyの空の配列に新しい行を追加するにはどうすればよいですか?


1
それが空の場合、なぜわざわざ?最初の行のみを保持する配列から始めます。
jonrsharpe 14年

10
空のnumpy配列に追加できるかどうか知りたいだけです。追加操作はループ内にあるため、このようなコードを記述する方がきれいな場合があります。
トニースターク

5
numpyのアレイ作業方法を考えると、あなたは、例えば参照してください、空の配列を構築する際にデータを入れてはるかに優れているstackoverflow.com/questions/568962/...を
jonrsharpe

回答:


227

必要な配列を「開始」する方法は次のとおりです。

arr = np.empty((0,3), int)

これは空の配列ですが、適切な次元を持っています。

>>> arr
array([], shape=(0, 3), dtype=int64)

次に、必ず軸0に沿って追加します。

arr = np.append(arr, np.array([[1,2,3]]), axis=0)
arr = np.append(arr, np.array([[4,5,6]]), axis=0)

しかし、@ jonrsharpeは正しいです。実際、ループで追加する場合は、最初の例のようにリストに追加し、最後にnumpy配列に変換する方がはるかに高速です。ループ中に意図された:

In [210]: %%timeit
   .....: l = []
   .....: for i in xrange(1000):
   .....:     l.append([3*i+1,3*i+2,3*i+3])
   .....: l = np.asarray(l)
   .....: 
1000 loops, best of 3: 1.18 ms per loop

In [211]: %%timeit
   .....: a = np.empty((0,3), int)
   .....: for i in xrange(1000):
   .....:     a = np.append(a, 3*i+np.array([[1,2,3]]), 0)
   .....: 
100 loops, best of 3: 18.5 ms per loop

In [214]: np.allclose(a, l)
Out[214]: True

numpythonicを使用する方法はアプリケーションによって異なりますが、次のようになります。

In [220]: timeit n = np.arange(1,3001).reshape(1000,3)
100000 loops, best of 3: 5.93 µs per loop

In [221]: np.allclose(a, n)
Out[221]: True

これを10 ^ 5回または10 ^ 6回実行する必要がある場合はどうなりますか?これらの方法はどちらも成り立たないようです。なにか提案を?
Rho Phi

@Robertoでは、通常、配列のサイズまたは形状(少なくとも、値が望ましい)を事前に決定する方法があります。あなたはそれができると思いますか?追加は、実際には1回または2回の操作でなければなりません。
askewchan 2016

時々、あなたは次元を推測することができない、それは人生です。ただし、十分な大きさの配列を割り当てて、そのビューに値を与えることができます。ただし、「マスク」する方法を見つける必要のある不要な値があるため、私はそれを好みません。このマスキングの考え方は、私の趣向に合わない。
Rho Phi

マスクする必要はなく、スライスするだけです!a = a[:N] 私はあなたがそれをベクトル化する方法を見つけるべきだと強く信じていますが(助けが必要な場合はあなたの詳細で新しい質問を投稿してください)、ループが終わるまでリストを使ってください。
askewchan 2016

29

これが私の解決策です:

arr = []
arr.append([1,2,3])
arr.append([4,5,6])
np_arr = np.array(arr)

結果の配列にはdtypeオブジェクトが含まれていますが、これは特定のケースでは受け入れられません
zer0fool

26

この場合、関数np.hstackおよびnp.vstackを使用できます。

arr = np.array([])
arr = np.hstack((arr, np.array([1,2,3])))
# arr is now [1,2,3]

arr = np.vstack((arr, np.array([4,5,6])))
# arr is now [[1,2,3],[4,5,6]]

np.concatenate関数を使用することもできます。

乾杯


7
2番目の配列の次元がones((2、2))のように> = 2の場合は機能しません。連結によって空から配列を構築している場合、境界のケースを回避する方法はないと思われます。
Taozi

毎回寸法をチェックする必要があるため、良い解決策ではありません。
SKR

1

カスタムdtype定義を使用して、私のために働いたのは:

import numpy

# define custom dtype
type1 = numpy.dtype([('freq', numpy.float64, 1), ('amplitude', numpy.float64, 1)])
# declare empty array, zero rows but one column
arr = numpy.empty([0,1],dtype=type1)
# store row data, maybe inside a loop
row = numpy.array([(0.0001, 0.002)], dtype=type1)
# append row to the main array
arr = numpy.row_stack((arr, row))
# print values stored in the row 0
print float(arr[0]['freq'])
print float(arr[0]['amplitude'])

1

ループ内の配列に新しい行を追加する場合は、空の配列を初期化するのではなく、ループを初めてループに直接割り当てる。

for i in range(0,len(0,100)):
    SOMECALCULATEDARRAY = .......
    if(i==0):
        finalArrayCollection = SOMECALCULATEDARRAY
    else:
        finalArrayCollection = np.vstack(finalArrayCollection,SOMECALCULATEDARRAY)

これは主にアレイの形状が不明な場合に役立ちます


0

forループを実行したいのですが、askewchanの方法ではうまく機能しないため、変更しました。

x=np.empty((0,3))
y=np.array([1 2 3])
for i in ...
x = vstack((x,y))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.