web-dev-qa-db-ja.com

Pythonの反復によりnumpy / scipyに配列を構築しますか?

しばしば、私はいくつかのデータを反復することによって配列を構築しています、例えば:

my_array = []
for n in range(1000):
  # do operation, get value 
  my_array.append(value)
# cast to array
my_array = array(my_array)

最初にリストを作成し、それを( "array"を使用して)配列にキャストする必要があることがわかりました。これらを回避する方法はありますか?これらすべてのキャスト呼び出しはコードを散らかします... "my_array"を最初から配列にして繰り返し構築するにはどうすればよいですか?

22
user248237

NumPyは 'fromiter'メソッドを提供します:

def myfunc(n):
    for i in range(n):
        yield i**2


np.fromiter(myfunc(5), dtype=int)

これは

array([ 0,  1,  4,  9, 16])
32

これを行うための推奨される方法は、ループの前に事前に割り当て、スライスとインデックス付けを使用して挿入することです

_my_array = numpy.zeros(1,1000)
for i in xrange(1000):
    #for 1D array
    my_array[i] = functionToGetValue(i)
    #OR to fill an entire row
    my_array[i:] = functionToGetValue(i)
    #or to fill an entire column
    my_array[:,i] = functionToGetValue(i)
_

numpy doesarray.resize()メソッドを提供しますが、ループ内でメモリを再割り当てするコストのため、これははるかに遅くなります。 必須に柔軟性がある場合、arrayからlistを作成するのが唯一の方法だと思います。

編集:あなたがデータにあまりにも多くのメモリを割り当てているのではないかと心配している場合、私は上記の方法を使って過剰に割り当て、ループが終わったら、array.resize()。これは、ループ内で配列を常に再割り当てするよりもfarfar速くなります。

編集:@ user248237のコメントに応じて、配列の1つの次元を知っていると仮定します(簡単にするため):

_my_array = numpy.array(10000, SOMECONSTANT)

for i in xrange(someVariable):
    if i >= my_array.shape[0]:
        my_array.resize((my_array.shape[0]*2, SOMECONSTANT))

    my_array[i:] = someFunction()

#lop off extra bits with resize() here
_

一般的な原則は、「必要以上に割り当てることです。状況が変わった場合は、可能な限り数回配列のサイズを変更してください」。サイズを2倍にすることは過剰と考えることができますが、実際には、これは他の言語のいくつかの標準ライブラリのいくつかのデータ構造で使用されている方法です(たとえば、_Java.util.Vector_はデフォルトでこれを行います。_std::vector_ C++でもこれを行います)。

15
Chinmay Kanchi