2017-10-21 45 views
2

Étant donné deux listes:Déterminer la position de chaque élément d'un tableau B dans un autre tableau A

In [518]: A 
Out[518]: [3, 4, 2, 1, 7, 6, 5] 

In [519]: B 
Out[519]: [4, 6] 

Chaque élément B existe dans A, sans exception.

Je voudrais récupérer un tableau d'index pour B comme vu dans A. Par exemple, 4 est présent dans l'index 1 dans A, et 6 est dans la position 5 pour B. Ma sortie attendue est [1, 5] pour ce scénario.

C'est ce que je l'ai fait pour obtenir l'index:

In [520]: np.flatnonzero(np.in1d(a, b)) 
Out[520]: array([1, 5]) 

Malheureusement, cela ne fonctionnera pas dans la plupart des cas. Par exemple, si B = [6, 4], ma méthode sort toujours [1, 5] quand il devrait sortir [5, 1].

Existe-t-il un moyen numpy efficace pour obtenir ce que j'essaie d'atteindre?

+1

assez sûr que cela est venu avant? Qu'en est-il des doublons? –

+0

L'aide de 'np.where' donne cet exemple exact:' ix = np.in1d ​​(A.ravel(), B) .reshape (A.shape); np où (ix) '. Désolé, ne correspond pas à votre deuxième critère. –

+0

@JonClements Peut-être, ne pouvait rien trouver ... Quant aux dupes en B, il est certain que toute méthode numpy digne de ce nom devrait être capable de les gérer correctement, mais ça ne me ferait pas de mal non plus. –

Répondre

2

IIUC:

In [71]: a 
Out[71]: array([3, 4, 2, 1, 7, 6, 5, 6, 4]) 

In [72]: b 
Out[72]: array([4, 6]) 

In [73]: np.where(a==b[:,None])[1] 
Out[73]: array([1, 8, 5, 7], dtype=int64) 

In [74]: b = np.array([6, 4]) 

In [75]: np.where(a==b[:,None])[1] 
Out[75]: array([5, 7, 1, 8], dtype=int64) 

MISE À JOUR: si vous avez besoin seulement des indices de premiers occurences (dans le cas où il y a des doublons dans tableau A), puis utilisez this solution from @Divakar, qui sera plus rapide:

In [84]: (a==b[:,None]).argmax(1) 
Out[84]: array([5, 1], dtype=int64) 
+0

Merci pour votre réponse! Je cherche '[1, 5]' dans la première instance et '[5, 1]' dans la seconde. Votre réponse semble être là mais pas tout à fait là :-) –

+0

@ cᴏʟᴅsᴘᴇᴇᴅ, j'ai changé votre tableau 'a' ;-) – MaxU

+0

Oh mon Dieu, je n'ai pas réalisé. Oui, c'est exactement ce que je cherche! Merci beaucoup! –

0

Je ne sais pas si elle est efficace, mais

[int(np.isin(A, B[x]).nonzero()[0]) for x in range(len(B))] 

semble correspondre à la facture. Si l'unicité est pas garantie alors la partie int() peut être retiré

+0

Honnêtement, j'ai pensé à cela moi-même, mais je voulais quelque chose d'un peu moins ... loopy. –

0

Si m=A.size et n=B.size l'où l'approche est O(mn). Vous pouvez rester à O((m+n)log(m+n)) par précaution sorte in1d sortie (avec des valeurs uniques ici):

A= np.unique(np.random.randint(0,100000,100000)) 
np.random.shuffle(A) 
B=np.unique(np.random.randint(0,10000,10000)) 
np.random.shuffle(B) 

def find(A,B): 
    pos=np.in1d(A,B).nonzero()[0] 
    return pos[A[pos].argsort()][B.argsort().argsort()] 

In [5]: np.allclose(np.where(np.equal.outer(B,A))[1],find(A,B)) 
Out[5]: True 

In [6]: %time np.where(np.equal.outer(B,A))[1] 
Wall time: 3.98 s 
Out[6]: array([88220, 13472, 12482, ..., 9795, 39524, 5727], dtype=int64) 

In [7]: %timeit find(A,B) 
22.6 ms ± 366 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)