web-dev-qa-db-ja.com

インデックスと値で1d NumPy配列を反復する方法

python dictの場合、iteritems()を使用してキーと値を同時にループできますが、NumPy配列にはこのような機能が見つかりません。次のようにidxを手動で追跡する必要があります。

idx = 0 
for j in theta:
   some_function(idx,j,theta)
   idx += 1

これを行うためのより良い方法はありますか?

10
user40780

いくつかの選択肢があります。以下は、1d NumPy配列を反復処理していることを前提としています。

range で繰り返します

for j in range(theta.shape[0]):  # or range(len(theta))
   some_function(j, theta[j], theta)

これは、 numba で動作する3つのソリューションの 唯一 であることに注意してください。 NumPy配列を明示的に反復処理することは、通常numbaまたはプリコンパイルの別の手段と組み合わせた場合にのみ効率的であるため、これは注目に値します。

enumerate で繰り返します

for idx, j in enumerate(theta):
   some_function(idx, j, theta)

1Dアレイ用の3つのソリューションの中で最も効率的です。以下のベンチマークをご覧ください。

np.ndenumerate で繰り返します

for idx, j in np.ndenumerate(theta):
   some_function(idx[0], j, theta)

idx[0]の追加のインデックス作成ステップに注意してください。これは、1d NumPy配列のインデックス(shapeなど)がシングルトンのタプルとして与えられるために必要です。 1次元配列の場合、np.ndenumerateは非効率的です。その利点は、多次元配列に対してのみ示されます。

パフォーマンスのベンチマーク

# Python 3.7, NumPy 1.14.3

np.random.seed(0)

arr = np.random.random(10**6)

def enumerater(arr):
    for index, value in enumerate(arr):
        index, value
        pass

def ranger(arr):
    for index in range(len(arr)):
        index, arr[index]
        pass

def ndenumerater(arr):
    for index, value in np.ndenumerate(arr):
        index[0], value
        pass

%timeit enumerater(arr)    # 131 ms
%timeit ranger(arr)        # 171 ms
%timeit ndenumerater(arr)  # 579 ms
23
jpp

たとえば、numpy.ndenumerateを使用できます

import numpy as np
test_array = np.arange(2, 3, 0.1)
for index, value in np.ndenumerate(test_array):
    print(index[0], value)

詳細については、 https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndenumerate.html を参照してください。

5
sushmit