2017-02-24 15 views
1

数値だけでなく、numpy配列の要素の位置も2番目のnumpy配列にも表示されます。その2番目の配列も。ここでPythonの要素の位置numpyの配列と同じ要素の位置が別の配列

は私が行うことができました最高の例です:

>>> a=np.arange(0.,15.) 
>>> a 
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 
     11., 12., 13., 14.]) 
>>> b=np.arange(4.,8.,.5) 
>>> b 
array([ 4. , 4.5, 5. , 5.5, 6. , 6.5, 7. , 7.5]) 
>>> [ (i,j) for (i,alem) in enumerate(a) for (j,blem) in enumerate(b) if alem==blem] 
[(4, 0), (5, 2), (6, 4), (7, 6)] 

誰もが速く何かを持って、numpyの特定、またはそれ以上の「神託」?

答えて

3

は(O((N + k)のログですN + K))(ナイーブアルゴリズムはO(NK)である)O用np.unique

uniq, inv = np.unique(np.r_[a, b], return_inverse=True) 
map = -np.ones((len(uniq),), dtype=int) 
map[inv[:len(a)]] = np.arange(len(a)) 
bina = map[inv[len(a):]] 
inds_in_b = np.where(bina != -1)[0] 
elements, inds_in_a = b[inds_in_b], bina[inds_in_b] 

またはあなたとソリューションが可能性があり、単純にソートa((N + k)のログ(K))

ソートされた配列 aについては
inds = np.argsort(a) 
aso = a[inds] 
bina = np.searchsorted(aso[:-1], b) 
inds_in_b = np.where(b == aso[bina])[0] 
elements, inds_in_a = b[inds_in_b], inds[bina[inds_in_b]] 
1

あなたは、aにもbの要素を見つけるためにnumpy.in1dを使用する論理インデックスとnumpy.whereは、相応の要素やインデックスを取得することができますすることができます:ここで

logic = np.in1d(b, a)  
list(zip(b[logic], np.where(logic)[0])) 
# [(4.0, 0), (5.0, 2), (6.0, 4), (7.0, 6)] 

b[logic], np.where(logic)[0] 
# (array([ 4., 5., 6., 7.]), array([0, 2, 4, 6])) 
3

、ここではそのオプションの引数を利用しnp.searchsortedを持つ別のアプローチがあります - sideleftとしてセットとright -

lidx = np.searchsorted(a,b,'left') 
ridx = np.searchsorted(a,b,'right') 
mask = lidx != ridx 
out = lidx[mask], np.flatnonzero(mask) 
     # for zipped o/p : zip(lidx[mask], np.flatnonzero(mask)) 

ランタイムテスト

アプローチ -

def searchsorted_where(a,b): # @Paul Panzer's soln 
    inds = np.argsort(a) 
    aso = a[inds] 
    bina = np.searchsorted(aso[:-1], b) 
    inds_in_b = np.where(b == aso[bina])[0] 
    return b[inds_in_b], inds_in_b 

def in1d_masking(a,b): # @Psidom's soln 
    logic = np.in1d(b, a)  
    return b[logic], np.where(logic)[0] 

def searchsorted_twice(a,b): # Proposed in this post 
    lidx = np.searchsorted(a,b,'left') 
    ridx = np.searchsorted(a,b,'right') 
    mask = lidx != ridx 
    return lidx[mask], np.flatnonzero(mask) 

タイミング -

ケース#1(質問からサンプルデータを使用して、それをスケールアップ):なしの場合の#1と同じ

In [2]: a=np.arange(0.,15000.) 
    ...: b=np.arange(4.,15000.,0.5) 
    ...: 

In [3]: %timeit searchsorted_where(a,b) 
    ...: %timeit in1d_masking(a,b) 
    ...: %timeit searchsorted_twice(a,b) 
    ...: 
1000 loops, best of 3: 721 µs per loop 
1000 loops, best of 3: 1.76 ms per loop 
1000 loops, best of 3: 1.28 ms per loop 

ケース#2(。 aに比べて比較的小さいbでelems)の:

In [4]: a=np.arange(0.,15000.) 
    ...: b=np.arange(4.,15000.,5) 
    ...: 

In [5]: %timeit searchsorted_where(a,b) 
    ...: %timeit in1d_masking(a,b) 
    ...: %timeit searchsorted_twice(a,b) 
    ...: 
10000 loops, best of 3: 77.4 µs per loop 
1000 loops, best of 3: 428 µs per loop 
10000 loops, best of 3: 128 µs per loop 

ケース#3(およびbで比較的はるかに少ないelems):あなたは私からの最初の2行をカットした場合

In [6]: a=np.arange(0.,15000.) 
    ...: b=np.arange(4.,15000.,10) 
    ...: 

In [7]: %timeit searchsorted_where(a,b) 
    ...: %timeit in1d_masking(a,b) 
    ...: %timeit searchsorted_twice(a,b) 
    ...: 
10000 loops, best of 3: 42.8 µs per loop 
1000 loops, best of 3: 392 µs per loop 
10000 loops, best of 3: 71.9 µs per loop 
+0

はどうなりますか?彼らは 'a'がソートされていない場合に備えているので、あなたのテスト条件の下で彼らは私が思うはずです;-) –

+0

@divakar Dang!宿題をつけるつもりはありませんでした! :)非常に有用で思いやりのある答えに非常に感謝します。皆さん、お返事いただきありがとうございます。 –

+0

Divakar私は自分自身をチェックしました。当然のことながら、最後の条件では、私の関数は時間の3/4を "argsort"とする(arange(15000))。真ん中の状態ではまだ2/3のままです。だから、可能な限り強力な方法であなたの方法論に抗議しなければならない;-) –

関連する問題