何かの最初のインデックスを返す Python リストのメソッドがあることは知っています。
>>> l = [1, 2, 3]
>>> l.index(2)
1
NumPy配列にそのようなものはありますか?
はい、検索する配列、array
、および値を指定すると、次のように使用できます。item
np.where
itemindex = numpy.where(array==item)
結果は、最初にすべての行インデックス、次にすべての列インデックスを持つタプルです。
たとえば、配列が 2 次元で、アイテムが 2 つの場所に含まれている場合、
array[itemindex[0][0]][itemindex[1][0]]
あなたのアイテムに等しいので、次のようになります。
array[itemindex[0][1]][itemindex[1][1]]
1 つの値のみの最初の出現のインデックスが必要な場合は、nonzero
(またはwhere
、この場合は同じことになります)を使用できます。
>>> t = array([1, 1, 1, 2, 2, 3, 8, 3, 8, 8])
>>> nonzero(t == 8)
(array([6, 8, 9]),)
>>> nonzero(t == 8)[0][0]
6
多くの値のそれぞれの最初のインデックスが必要な場合は、明らかに上記と同じことを繰り返し行うことができますが、より高速なトリックがあります。以下は、各サブシーケンスの最初の要素のインデックスを見つけます。
>>> nonzero(r_[1, diff(t)[:-1]])
(array([0, 3, 5, 6, 7, 8]),)
3 のサブシーケンスと 8 のサブシーケンスの両方の開始点が検出されることに注意してください。
[ 1、 1 、 1 、2、 2 、3、8、3、8、 8 ]
したがって、各値の最初の出現を見つけることとは少し異なります。あなたのプログラムでは、ソートされたバージョンの をt
操作して、必要なものを取得できる場合があります。
>>> st = sorted(t)
>>> nonzero(r_[1, diff(st)[:-1]])
(array([0, 3, 5, 7]),)
最初のインデックスを見つけるために、に基づいて非常にパフォーマンスが高く便利なnumbaの代替を追加するだけです。np.ndenumerate
from numba import njit
import numpy as np
@njit
def index(array, item):
for idx, val in np.ndenumerate(array):
if val == item:
return idx
# If no item was found return None, other return types might be a problem due to
# numbas type inference.
これは非常に高速で、多次元配列を自然に処理します。
>>> arr1 = np.ones((100, 100, 100))
>>> arr1[2, 2, 2] = 2
>>> index(arr1, 2)
(2, 2, 2)
>>> arr2 = np.ones(20)
>>> arr2[5] = 2
>>> index(arr2, 2)
(5,)
これは、 orを使用するどのアプローチよりもはるかに高速です (操作を短絡しているため) 。np.where
np.nonzero
ただし、多次元配列を適切np.argwhere
に処理することもできます (手動でタプルにキャストする必要があり、ショートサーキットではありません) が、一致が見つからない場合は失敗します。
>>> tuple(np.argwhere(arr1 == 2)[0])
(2, 2, 2)
>>> tuple(np.argwhere(arr2 == 2)[0])
(5,)
これを別のものへのインデックスとして使用する場合、配列がブロードキャスト可能であれば、ブール値のインデックスを使用できます。明示的なインデックスは必要ありません。これを行う最も簡単な方法は、単純に真理値に基づいてインデックスを作成することです。
other_array[first_array == item]
ブール演算は次のように機能します。
a = numpy.arange(100)
other_array[first_array > 50]
ゼロ以外のメソッドもブール値を取ります。
index = numpy.nonzero(first_array == item)[0][0]
2 つのゼロは、インデックスのタプル (first_array が 1D であると仮定) 用であり、インデックスの配列の最初の項目用です。
任意の基準でインデックスを作成するには、次のようにします。
In [1]: from numpy import *
In [2]: x = arange(125).reshape((5,5,5))
In [3]: y = indices(x.shape)
In [4]: locs = y[:,x >= 120] # put whatever you want in place of x >= 120
In [5]: pts = hsplit(locs, len(locs[0]))
In [6]: for pt in pts:
.....: print(', '.join(str(p[0]) for p in pt))
4, 4, 0
4, 4, 1
4, 4, 2
4, 4, 3
4, 4, 4
list.index() が行うことを実行する簡単な関数を次に示します。ただし、見つからない場合は例外を発生させません。注意してください -- これはおそらく、大規模な配列では非常に遅くなります。メソッドとして使用したい場合は、おそらくこれを配列にサルパッチすることができます。
def ndindex(ndarray, item):
if len(ndarray.shape) == 1:
try:
return [ndarray.tolist().index(item)]
except:
pass
else:
for i, subarray in enumerate(ndarray):
try:
return [i] + ndindex(subarray, item)
except:
pass
In [1]: ndindex(x, 103)
Out[1]: [4, 0, 3]
1D 配列の場合は、 をお勧めします。これは と の両方とnp.flatnonzero(array == value)[0]
同等ですが、1 要素のタプルをボックス化解除することの醜さを回避します。np.nonzero(array == value)[0][0]
np.where(array == value)[0][0]
NumPy には、これを実現するために組み合わせることができる操作が多数あります。これは item に等しい要素のインデックスを返します:
numpy.nonzero(array - item)
次に、リストの最初の要素を取得して、単一の要素を取得できます。
ndindex を使用する
サンプル配列
arr = np.array([[1,4],
[2,3]])
print(arr)
...[[1,4],
[2,3]]
インデックスと要素タプルを格納するための空のリストを作成します
index_elements = []
for i in np.ndindex(arr.shape):
index_elements.append((arr[i],i))
タプルのリストを辞書に変換します
index_elements = dict(index_elements)
キーは要素で、値はそれらのインデックスです - キーを使用してインデックスにアクセスします
index_elements[4]
出力
... (0,1)