2015-09-18 17 views
6

Python 2.7 kullanıyorum. Ben B'de mevcut olduğu bir elemanların indeksleri bulmak için iki dizi A ve B var, ben de vardır B elemanların endekslerini almak istiyorumİki dizide ortak değerlerin indekslerini bulun

A_inds = np.in1d(A,B) 

yapabilirsiniz A'da, yani yukarıdaki kodu kullanarak bulduğum aynı örtüşen öğelerin B'deki indeksler.

B_inds = np.in1d(B,A) 

ama gereksiz olması gerektiği gibi bu ekstra hesaplama görünüyor şu şekildedir:

Şu anda yine aynı çizgiyi çalıştırıyorum. Hem A_inds hem de B_inds'u edinmenin daha hesaplamalı verimli bir yolu var mı?

Liste veya dizi yöntemlerini kullanarak açılıyorum.

+0

Giriş dizisi boyutları nedir? 1D mi? – Divakar

+0

Büyük. 10^6 veya 10^7 sırasına göre. – berkelem

+1

Bu dizilerin benzersiz öğeleri var mı? Sıralandı mı? – Divakar

cevap

3

np.unique ve np.searchsorted bunu çözmek için birlikte kullanılabilir - iki giriş diziler zaten sorted ve unique, varsa

In [233]: def org_app(A,B): 
    ...:  return np.in1d(A,B), np.in1d(B,A) 
    ...: 

In [234]: A = np.random.randint(0,10000,(10000)) 
    ...: B = np.random.randint(0,10000,(10000)) 
    ...: 

In [235]: np.allclose(org_app(A,B)[0],unq_searchsorted(A,B)[0]) 
Out[235]: True 

In [236]: np.allclose(org_app(A,B)[1],unq_searchsorted(A,B)[1]) 
Out[236]: True 

In [237]: %timeit org_app(A,B) 
100 loops, best of 3: 7.69 ms per loop 

In [238]: %timeit unq_searchsorted(A,B) 
100 loops, best of 3: 5.56 ms per loop 

- sonuçları

def unq_searchsorted(A,B): 

    # Get unique elements of A and B and the indices based on the uniqueness 
    unqA,idx1 = np.unique(A,return_inverse=True) 
    unqB,idx2 = np.unique(B,return_inverse=True) 

    # Create mask equivalent to np.in1d(A,B) and np.in1d(B,A) for unique elements 
    mask1 = (np.searchsorted(unqB,unqA,'right') - np.searchsorted(unqB,unqA,'left'))==1 
    mask2 = (np.searchsorted(unqA,unqB,'right') - np.searchsorted(unqA,unqB,'left'))==1 

    # Map back to all non-unique indices to get equivalent of np.in1d(A,B), 
    # np.in1d(B,A) results for non-unique elements 
    return mask1[idx1],mask2[idx2] 

Süre testleri ve doğrulamak performans artışı önemli olacaktır. Böylece çözüm işlevi basitleştirmek olur için -

def unq_searchsorted_v1(A,B): 
    out1 = (np.searchsorted(B,A,'right') - np.searchsorted(B,A,'left'))==1 
    out2 = (np.searchsorted(A,B,'right') - np.searchsorted(A,B,'left'))==1 
    return out1,out2 

sonraki çalışma zamanı testlerinin -

In [275]: A = np.random.randint(0,100000,(20000)) 
    ...: B = np.random.randint(0,100000,(20000)) 
    ...: A = np.unique(A) 
    ...: B = np.unique(B) 
    ...: 

In [276]: np.allclose(org_app(A,B)[0],unq_searchsorted_v1(A,B)[0]) 
Out[276]: True 

In [277]: np.allclose(org_app(A,B)[1],unq_searchsorted_v1(A,B)[1]) 
Out[277]: True 

In [278]: %timeit org_app(A,B) 
100 loops, best of 3: 8.83 ms per loop 

In [279]: %timeit unq_searchsorted_v1(A,B) 
100 loops, best of 3: 4.94 ms per loop 
+0

Bu 3 diziye genişletilebilir mi? (ya da n dizileri, hatta?) – hm8

+0

@ hm8 Yeni bir soru, kolay bir uzantıya benzemediği için uygun olacağını düşünüyorum. – Divakar

1

Basit çoklu işlem uygulaması size biraz daha hız alacak:

import time 
import numpy as np 

from multiprocessing import Process, Queue 

a = np.random.randint(0, 20, 1000000) 
b = np.random.randint(0, 20, 1000000) 

def original(a, b, q): 
    q.put(np.in1d(a, b)) 

if __name__ == '__main__': 
    t0 = time.time() 
    q = Queue() 
    q2 = Queue() 
    p = Process(target=original, args=(a, b, q,)) 
    p2 = Process(target=original, args=(b, a, q2)) 
    p.start() 
    p2.start() 
    res = q.get() 
    res2 = q2.get() 

    print time.time() - t0 

>>> 0.21398806572 

Divakar en unq_searchsorted(A,B) yöntem aldı Makinemde 0.271834135056 saniye.

+0

Bunun için teşekkürler - kesinlikle yararlı olacaktır. Şimdilik, tek bir çekirdeğin en hızlı yöntemini aradığımdan, tüm kodu daha sonra birkaç çekirdek üzerinde dağıtacağım. – berkelem

İlgili konular