回答:
はい、ここにNumPy配列array
、および値が指定された場合のitem
検索結果を示します。
itemindex = numpy.where(array==item)
結果は、最初にすべての行インデックス、次にすべての列インデックスを持つタプルです。
たとえば、配列が2次元で、2つの場所にアイテムが含まれている場合
array[itemindex[0][0]][itemindex[1][0]]
あなたのアイテムと等しいでしょう
array[itemindex[0][1]][itemindex[1][1]]
rows, columns = np.where(array==item); first_idx = sorted([r for r, c in zip(rows, columns) if c == 0])[0]
np.argwhere
ここで少し役立つでしょう:itemindex = np.argwhere(array==item)[0]; array[tuple(itemindex)]
where
任意の配列で動作し、3次元アレイ等に使用されたときの長さ3のタプルを返すであろう
値が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]),)
3sの両方のサブシーケンスと8sの両方のサブシーケンスの先頭を見つけることに注意してください。
[ 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]),)
r_
か?
r_
連結します。または、より正確には、スライスオブジェクトを各軸に沿った連結に変換します。hstack
代わりに使用できました。混乱が少ないかもしれません。の詳細については、ドキュメントを参照してくださいr_
。もありc_
ます。
vals, locs = np.unique(t, return_index=True)
NumPy配列を空中のリストに変換して、そのインデックスを取得することもできます。例えば、
l = [1,2,3,4,5] # Python list
a = numpy.array(l) # NumPy array
i = a.tolist().index(2) # i will return index of 2
print i
1を出力します。
[find_list.index(index_list[i]) for i in range(len(index_list))]
find_list
、NumPy配列object
(または適切な具体的なもの)のNumPy配列に変換して、を実行しますfind_arr[index_list]
。
非常に高性能で便利な numbanp.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,)
これは、またはを使用するアプローチよりもはるかに高速です(操作を短絡するため)。np.where
np.nonzero
ただしnp.argwhere
も対処でき優雅に多次元配列で(手動タプルにキャストする必要があるだろうし、それが短絡していないのです)が、一致が見つからない場合、それは失敗します。
>>> tuple(np.argwhere(arr1 == 2)[0])
(2, 2, 2)
>>> tuple(np.argwhere(arr2 == 2)[0])
(5,)
@njit
短縮であるjit(nopython=True)
機能は完全にオンザフライPythonインタプリタコールが完全に除去されるように、最初の実行時にコンパイルされますすなわち。
これを別のものへのインデックスとして使用する場合、配列がブロードキャスト可能な場合はブールインデックスを使用できます。明示的なインデックスは必要ありません。これを行う最も簡単な方法は、真理値に基づいてインデックスを作成することです。
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であると想定)、およびインデックスの配列の最初のアイテム用です。
l.index(x)
iがリスト内で最初に出現するxのインデックスになるような最小のiを返します。
index()
最初の一致を見つけた後に停止するようにPython の関数が実装されていると安全に想定でき、これにより最適な平均パフォーマンスが得られます。
NumPy配列の最初の一致の後に停止する要素を見つけるには、イテレータ(ndenumerate)を使用します。
In [67]: l=range(100)
In [68]: l.index(2)
Out[68]: 2
NumPy配列:
In [69]: a = np.arange(100)
In [70]: next((idx for idx, val in np.ndenumerate(a) if val==2))
Out[70]: (2L,)
要素が見つからない場合、どちらのメソッドindex()
もnext
エラーを返すことに注意してください。ではnext
、要素が見つからない場合に2番目の引数を使用して特別な値を返すことができます。
In [77]: next((idx for idx, val in np.ndenumerate(a) if val==400),None)
numpyの中に他の機能があります(argmax
、where
、およびnonzero
)配列の要素を検索するために使用されるが、彼らはすべてを探して全体の配列を通過するという欠点持つことができるすべてのための最初の要素を発見するために最適化されていない、出現を。また、配列where
をnonzero
返すため、最初の要素を選択してインデックスを取得する必要があることにも注意してください。
In [71]: np.argmax(a==2)
Out[71]: 2
In [72]: np.where(a==2)
Out[72]: (array([2], dtype=int64),)
In [73]: np.nonzero(a==2)
Out[73]: (array([2], dtype=int64),)
大規模な配列の場合、イテレーターを使用したソリューションの方が、検索された項目が配列の先頭にある場合(%timeit
IPythonシェルで使用)の方が速いことを確認するだけです。
In [285]: a = np.arange(100000)
In [286]: %timeit next((idx for idx, val in np.ndenumerate(a) if val==0))
100000 loops, best of 3: 17.6 µs per loop
In [287]: %timeit np.argmax(a==0)
1000 loops, best of 3: 254 µs per loop
In [288]: %timeit np.where(a==0)[0][0]
1000 loops, best of 3: 314 µs per loop
これは未解決のNumPy GitHubの問題です。
%timeit next((idx for idx, val in np.ndenumerate(a) if val==99999))
か?なぜそれが1000倍遅いのか疑問に思っている場合-numpy配列に対するPythonループが悪名高いほど遅いためです。
argmax
し、where
(配列の最後に要素を検索)この場合にははるかに高速です
1次元のソートされた配列の場合、NumPy整数(位置)を返すnumpy.searchsortedを使用する方がはるかに簡単で効率的なO(log(n))です。例えば、
arr = np.array([1, 1, 1, 2, 3, 3, 4])
i = np.searchsorted(arr, 3)
配列がすでにソートされていることを確認してください
また、searchsortedの主な目的は、順序を維持するために要素を挿入する必要があるインデックスを見つけることなので、返されたインデックスiに実際に検索された要素が含まれているかどうかを確認します。
if arr[i] == 3:
print("present")
else:
print("not present")
任意の基準でインデックスを作成するには、次のようにすることができます。
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]
np.where()から最初の要素を選択する代わりに、次のように列挙型と一緒にジェネレータ式を使用することもできます。
>>> import numpy as np
>>> x = np.arange(100) # x = array([0, 1, 2, 3, ... 99])
>>> next(i for i, x_i in enumerate(x) if x_i == 2)
2
2次元配列の場合、次のようになります。
>>> x = np.arange(100).reshape(10,10) # x = array([[0, 1, 2,... 9], [10,..19],])
>>> next((i,j) for i, x_i in enumerate(x)
... for j, x_ij in enumerate(x_i) if x_ij == 2)
(0, 2)
このアプローチの利点は、最初の一致が見つかった後で配列の要素のチェックを停止するのに対して、np.whereはすべての要素の一致をチェックすることです。配列の初期に一致がある場合、ジェネレータ式はより高速になります。
None
フォールバックとして戻る場合は、になりnext((i for i, x_i in enumerate(x) if x_i == 2), None)
ます。
NumPyには、おそらくこれを実現するために組み合わせることができる多くの操作があります。これはitemに等しい要素のインデックスを返します:
numpy.nonzero(array - item)
次に、リストの最初の要素を取得して、単一の要素を取得します。
numpy_indexedパッケージ(免責事項、私はその作者午前)numpy.ndarrayためlist.indexのベクトル化と同等が含まれています。あれは:
sequence_of_arrays = [[0, 1], [1, 2], [-5, 0]]
arrays_to_query = [[-5, 0], [1, 0]]
import numpy_indexed as npi
idx = npi.indices(sequence_of_arrays, arrays_to_query, missing=-1)
print(idx) # [2, -1]
このソリューションは、パフォーマンスをベクトル化し、ndarrayに一般化し、欠損値を処理するさまざまな方法を備えています。
注:これはPython 2.7バージョン用です
ラムダ関数を使用して問題を処理でき、NumPy配列とリストの両方で機能します。
your_list = [11, 22, 23, 44, 55]
result = filter(lambda x:your_list[x]>30, range(len(your_list)))
#result: [3, 4]
import numpy as np
your_numpy_array = np.array([11, 22, 23, 44, 55])
result = filter(lambda x:your_numpy_array [x]>30, range(len(your_list)))
#result: [3, 4]
そして、あなたは使うことができます
result[0]
フィルターされた要素の最初のインデックスを取得します。
Python 3.6の場合は、
list(result)
の代わりに
result
<filter object at 0x0000027535294D30>
Python 3が実行されます(Python 3.6.3でテスト済み)。たぶんPython 3のアップデートですか?