2011-11-24 8 views
24

두 개의 1D 배열 x & y가 있는데, 하나는 다른 배열보다 작습니다. x에서 y의 모든 원소의 인덱스를 찾으려고합니다.Numpy : 한 배열의 모든 요소에 대해 다른 배열의 색인을 찾으십시오.

나는 이것을하기위한 두 가지 간단한 방법을 찾았습니다. 첫 번째 방법은 느리고 두 번째 방법은 메모리 집약적입니다.

느린 방법

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)) 

는 빠른 방법 이하 메모리 집약적 인 방법이 있습니까? 이상적으로 검색은 목록에서 한 가지가 아니라 많은 것을 검색하므로 병렬 처리가 약간 더 편리합니다. y의 모든 요소가 실제로 x에 있다고 가정하지 않으면 보너스 포인트가됩니다.

답변

15

조 킹턴 (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] 
+0

아, 훌륭한 코드 조각. Joe 코드를 일반화 해 주셔서 감사합니다! – Chris

12

어때?

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] 
+0

. 참으로 훨씬 빠릅니다. y를 하위의 x가되도록 입력을 제한하려면'assert na.all (na.intersect1d (x, y) == na.sort (y))'를 포함합니다. 감사! – Chris

15

내가 원 - 제안 할 결과는 x에서 발견 된 y의 요소에 해당하는 x 배열에 대한 인덱스가있는 배열입니다.

필요에 따라 numpy없이 사용할 수 있습니다.

+0

이것은 선택된 답변이어야합니다. x 값이 반복되거나 존재하지 않는 경우에도 작동합니다. searchsorted와 관련된 대답은 복잡하고 이상하며 부자연 스럽습니다. –

+5

이것은 x에 존재하는 y의 원소의 색인을 반환하지만 반환 된 색인의 순서는 x의 값의 순서와 일치하지 않습니다. x = np.array ([1,2,3,4,5]; y = np.array ([5,4,3,2,1]) 위의 메소드는 array ([0,1, 2,3,4]), 그래서 x [0] = 1은 y [0] = 5와 일치합니다 ... – ccbunney

+0

훌륭하고 우아한 코드 – Orangeblue

0

numpy_indexed 패키지 (면책 조항 : 나는 그것의 저자) 정확히이 수행하는 기능이 포함되어 Y의 모든 요소가 X에 존재하는 경우

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

그것은 현재 KeyError를 인상됩니다; 그러나 아마도 나는 kwarg를 추가해야합니다. 그래서 kwarg를 추가하여 -1 또는 그와 같은 항목을 표시하도록 선택할 수 있습니다.

구현이 비슷한 선상에 있기 때문에 현재 허용되는 답변과 동일한 효율성을 가져야합니다. 그러나 numpy_indexed는 더 유연하며 다차원 배열의 행 인덱스를 검색 할 수도 있습니다.

EDIT : 누락 된 값의 처리를 변경했습니다. '누락'kwarg는 이제 'raise', 'ignore'또는 'mask'로 설정할 수 있습니다. 후자의 경우, 동일한 길이의 마스크 된 배열을 가져오고, 여기에서 .compressed()를 호출하여 유효한 인덱스를 얻을 수 있습니다. 이것이 알아야 할 사항이라면 npi.contains (x, y)도 있습니다.

4

난 그냥 이런 짓을 했을까 :

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

메모리 - 돼지의 방법과는 달리,이 직접 x와 y 모두 2 차원 배열을 생성하지 않고 2D 부울 배열을 생성하는 브로드 캐스트를 사용합니다.

+1

기록을 위해, 이것은 메모리를 hogs합니다. 잘, – romeric

+0

그래, 내가 의미하는 바는 적은 양의 메모리를 필요로하지 않는다. 내 버전은 적은 메모리를 차지하면서 코드를 깨끗하게 유지하는 데 좋은 절충안이라고 생각한다. –

0

더 직접적인 해결책은 배열을 정렬 할 것으로 기대하지 않습니다.

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] 
관련 문제