配列内の何かの最初のインデックスを返すNumPy関数はありますか?

StackOverflow https://stackoverflow.com/questions/432112

  •  08-07-2019
  •  | 
  •  

質問

Pythonリストが何かの最初のインデックスを返すメソッドがあることは知っています:

>>> l = [1, 2, 3]
>>> l.index(2)
1

NumPy配列にはそのようなものがありますか?

役に立ちましたか?

解決

はい、NumPy配列 array と、検索する値 item を指定した場合の答えは次のとおりです。

itemindex = numpy.where(array==item)

結果は、最初にすべての行インデックス、次にすべての列インデックスを持つタプルです。

たとえば、配列が2次元であり、2つの場所にアイテムが含まれている場合

array[itemindex[0][0]][itemindex[1][0]]

アイテムと同等になるため、

array[itemindex[0][1]][itemindex[1][1]]

numpy.where

他のヒント

最初に出現する 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]),)

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が印刷されます。

これを他の何かへのインデックスとして使用する場合、配列がブロードキャスト可能であればブール型インデックスを使用できます。明示的なインデックスは必要ありません。これを行うための絶対的に最も簡単な方法は、真理値に基づいて単純にインデックスを付けることです。

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 を返します。

Pythonの index()関数は、最初の一致が見つかった後に停止するように実装されているため、最適な平均パフォーマンスが得られると安全に想定できます。

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 )があります。しかし、それらはすべて、配列全体を検索して all の出現を探すという欠点があるため、最初の要素を見つけるために最適化されていません。また、 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),)

時間の比較

大規模な配列の場合、イテレータを使用したソリューションの方が、検索アイテムが配列の先頭にある場合に高速になります (IPythonシェルで%timeit を使用) :

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の問題です。

関連項目: Numpy:値の最初のインデックスをすばやく見つける

任意の基準でインデックスを作成するには、次のようにします:

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] をお勧めします。これは、 np.nonzero(array == value)[0 ] [0] および np.where(array == value)[0] [0] ですが、1要素タプルのボックス化解除のugさを避けています。

NumPyには、これを達成するためにおそらくまとめることができる多くの操作があります。これは、アイテムに等しい要素のインデックスを返します:

numpy.nonzero(array - item)

リストの最初の要素を取得して、単一の要素を取得できます。

1次元の並べ替え配列の場合、 numpy.searchsorted は、NumPy整数(位置)を返します。たとえば、

arr = np.array([1, 1, 1, 2, 3, 3, 4])
i = np.searchsorted(arr, 3)

配列が既にソートされていることを確認してください

また、返されたインデックスiに実際に検索された要素が含まれているかどうかを確認します。searchsortedの主な目的は、順序を維持するために要素を挿入するインデックスを見つけることです。

if arr[i] == 3:
    print("present")
else:
    print("not present")

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はすべての要素の一致をチェックすることです。配列の早い段階で一致する場合、ジェネレーター式は高速になります。

numpy_indexed パッケージ(免責事項、私はその著者)には、list.indexのベクトル化された同等物が含まれています。 numpy.ndarray;つまり:

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]

このソリューションは、ベクトル化されたパフォーマンスを持ち、ndarraysに一般化し、欠損値を処理するさまざまな方法があります。

注:これは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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top