web-dev-qa-db-ja.com

Numpy:ある配列のすべての要素について、別の配列でインデックスを見つけます

2つの1次元配列xとyがあり、一方が他方より小さくなっています。 xのyのすべての要素のインデックスを見つけようとしています。

私はこれを行う2つの素朴な方法を見つけました。1つ目は遅く、2つ目はメモリを大量に消費します。

遅い方法

indices= []
for iy in y:
    indices += np.where(x==iy)[0][0]

メモリーホッグ

xe = np.outer([1,]*len(x), y)
ye = np.outer(x, [1,]*len(y))
junk, indices = np.where(np.equal(xe, ye))

より速い方法またはより少ないメモリ集約的なアプローチはありますか?理想的には、リスト内の1つではなく多くのものを検索するという事実を利用して検索を行うので、並列化の影響を少し受けやすくなります。 yのすべての要素が実際にxにあると想定しない場合のボーナスポイント。

39
Chris

Joe Kingtonが言ったように、 searchsorted() は要素を非常に迅速に検索できます。 xにない要素を処理するには、元のyで検索結果を確認し、マスクされた配列を作成します。

import numpy as np
x = np.array([3,5,7,1,9,8,6,6])
y = np.array([2,1,5,10,100,6])

index = np.argsort(x)
sorted_x = x[index]
sorted_index = np.searchsorted(sorted_x, y)

yindex = np.take(index, sorted_index, mode="clip")
mask = x[yindex] != y

result = np.ma.array(yindex, mask=mask)
print result

結果は次のとおりです。

[-- 3 1 -- -- 6]
27
HYRY

私は一行の解決策を提案したいと思います:

indices = np.where(np.in1d(x, y))[0]

結果は、xで見つかったyの要素に対応するx配列のインデックスを持つ配列です。

必要に応じて、numpy.whereなしで使用できます。

27
RomanS

これはどう?

Yのすべての要素がxにあると想定しています(そうでない要素でも結果が返されます)。ただし、はるかに高速です。

import numpy as np

# Generate some example data...
x = np.arange(1000)
np.random.shuffle(x)
y = np.arange(100)

# Actually preform the operation...
xsorted = np.argsort(x)
ypos = np.searchsorted(x[xsorted], y)
indices = xsorted[ypos]
20
Joe Kington

これはより明確なバージョンだと思います:

_np.where(y.reshape(y.size, 1) == x)[1]
_

indices = np.where(y[:, None] == x[None, :])[1]より。 xを2Dにブロードキャストする必要はありません。

ここや他の場所に投稿されているsearchsorted()またはin1d()ベースのソリューションとは異なり、上記は重複で機能し、ソートされているかどうかを気にしないため、このタイプのソリューションが最良であることがわかりました。 xを特定のカスタムオーダーにしたかったので、これは私にとって重要でした。

6
hermidalc

私はこれを行うでしょう:

indices = np.where(y[:, None] == x[None, :])[1]

メモリーを独占する方法とは異なり、これはブロードキャストを利用して、xとyの両方の2D配列を作成することなく、2Dブール配列を直接生成します。

5
Jun Saito

numpy_indexed パッケージ(免責事項:私は作成者です)には、これを正確に実行する関数が含まれています。

import numpy_indexed as npi
indices = npi.indices(x, y, missing='mask')

現在、yのすべての要素がxに存在しない場合、KeyErrorが発生します。しかし、おそらく、そのような項目に-1か何かでマークを付けることができるように、クワーグを追加する必要があります。

実装は同様のラインに沿っているため、現在受け入れられている回答と同じ効率になるはずです。ただし、numpy_indexedはより柔軟で、たとえば、多次元配列の行のインデックスを検索することもできます。

編集:欠損値の処理を変更しました。 「missing」クワーグは「raise」、「ignore」、または「mask」で設定できるようになりました。後者の場合、有効なインデックスを取得するために.compressed()を呼び出すことができる同じ長さのyのマスクされた配列を取得します。これがあなたが知る必要があるすべてであるならば、npi.contains(x、y)もあることに注意してください。

3

次のコード行を使用します:-

インデックス= np.where(y [:,なし] == x [なし、:])[1]

1
Kaushal Gupta

より直接的な解決策は、配列がソートされることを期待していません。

import pandas as pd
A = pd.Series(['amsterdam', 'delhi', 'chromepet', 'tokyo', 'others'])
B = pd.Series(['chromepet', 'tokyo', 'tokyo', 'delhi', 'others'])

# Find index position of B's items in A
B.map(lambda x: np.where(A==x)[0][0]).tolist()

結果は次のとおりです。

[2, 3, 3, 1, 4]
0
Selva