2011-01-16 2 views
3

두 개의 동일한 크기의 numpy.array 객체 (둘 다 1 차원)가 있는데, 그 중 하나에는 시작 인덱스 위치 목록이 들어 있고, 다른 하나에는 끝 인덱스 위치 (또는 시작 위치 및 창 길이 목록이 있다고 말할 수 있습니다). 중요한 경우 시작 위치와 끝 위치에서 형성된 슬라이스가 겹치지 않도록 보장됩니다. 루프를 사용하지 않고도 다른 배열 객체에 대한 인덱스를 형성하기 위해 이러한 시작 및 끝 위치를 사용하는 방법을 파악하려고합니다. 예를 들어Numpy 인덱스를 주어진 시작 및 종료 위치 목록으로 구성하십시오.

:

import numpy as np 
start = np.array([1,7,20]) 
end = np.array([3,10,25]) 

somearray[1,2,7,8,9,20,21,22,23,24]) 

답변

3

나는

np.r_[tuple(slice(s, e) for s, e in zip(start, end))] 

편집을 사용합니다 :

def indices(start, end): 
    lens = end - start 
    np.cumsum(lens, out=lens) 
    i = np.ones(lens[-1], dtype=int) 
    i[0] = start[0] 
    i[lens[:-1]] += start[1:] 
    i[lens[:-1]] -= end[:-1] 
    np.cumsum(i, out=i) 
    return i 

이것은 단지 하나의 일시적 NumPy와 배열 (lens)를 생성하고 훨씬 빠릅니다 : 여기 파이썬 루프를 사용하지 않는 솔루션입니다 다른 솔루션보다

+0

감사합니다. Sven, 그러나 저는 이것이 Joe Kington이 제공 한 해결책보다 조금 느린 것을 알았습니다. – Abiel

+0

@Abiel : 어제 시간 지낼 시간이 없었어요. 다음은 또 다른 시도입니다. –

+0

Sven - 업데이트 된 솔루션을 제공해 주셔서 감사합니다. 이 제품이 최고의 성능을 발휘했습니다. – Abiel

2

NumPy와의 arange를 참조 할 각 개별 시퀀스 함께 그래서 그냥 문자열을 만듭니다. 이건 어때?

In [11]: idx = np.hstack([np.arange(s,e) for s,e in zip(start, end)]) 

In [12]: idx 
Out[12]: array([ 1, 2, 7, 8, 9, 20, 21, 22, 23, 24]) 

그리고 나서 somearray[idx]에 액세스 할 수 있습니다.

+1

마찬가지로 np.hstack ([np.r_ [s : e]는 s, e는 zip (start, end)])') 할 수 있습니다. 그것은 당신이'numpy.r_'에 익숙하지 않다면 조금 읽기 어렵습니다. –

+0

감사합니다 앤드류와 조. 한 가지 질문은 목록 작성을 피하면서 이것을 수행 할 수있는 방법이 있습니까?분명히 이것은 빠르지 만, 나는 여전히 내 함수의 런타임 대부분이 idx를 빌드하는 라인에서 발생한다는 것을 알게된다. (나머지 함수는 numpy 루틴을 사용하여 특정 길이 기준과 일치하는 창에 대한 시작 및 끝 위치를 식별한다.) – Abiel

+0

이 두 가지 방법 모두 중간 배열을 생성하고 단순히 배열의 정수 인덱스를 생성합니다. 큰 배열을 말하면 낭비입니다. –

-1

예제 배열과 일치하지 않는 "시작 위치 및 창 길이 목록이 있다고 말할 수 있습니다."라고하셨습니다. 당신이 당신의 요소를이 방법으로 얻을 수

start 경우 시작을 나타내고 end길이입니다 :

>>> [i for iter in [range(s,s+e) for s,e in zip(start,end)] for i in iter] 
[1, 2, 3, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 21, 22, 23, 24, 25, 26, 
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44] 

당신이 당신의 예를 배열을 일치 시키려면 및 end 정말 끝나는 요소를 -

>>> [i for iter in [range(*t) for t in zip(start,end)] for i in iter] 
[1, 2, 7, 8, 9, 20, 21, 22, 23, 24] 
>>> somearray=np.array(_) 
>>> somearray 
array([1, 2, 7, 8, 9, 20, 21, 22, 23, 24]) 

대체 :

01 일
당신은 당신의 요소를 이런 식으로 얻을 수 있습니다
>>> sum([range(*t) for t in zip(start,end)],[]) 
[1, 2, 7, 8, 9, 20, 21, 22, 23, 24] 

튜플에 설명 된 정수 목록을 numpy 배열의 색인으로 생성하는 것만 기억하십시오. 귀하의 경우 faster/better이면 xrangerange을 사용할 수 있습니다.

+0

질문자가 원하는 것이 아니라 ... –

+0

@Andrew Jaffe : 그는 다른 두 가지를 말했고 둘 다 대답했습니다. –

+0

(내가이 말을하지 않았을 때 ....) –

0

이 방법에 대해 :

>>> import numpy as np 
>>> start = np.array([1,7,20]) 
>>> end = np.array([3,10,25]) 
>>> na=np.fromiter(sum([range(s,e) for s,e in zip(start,end)],[]),np.int) 
>>> na 
array([ 1, 2, 7, 8, 9, 20, 21, 22, 23, 24]) 

장점은 1)에는 중간 NumPy와 플로트 배열 없다; 2) 결과 배열은 다른 numpy 배열을 가장 효율적으로 처리 할 수있는 정수입니다.

+0

감사합니다 drewk, 불행히도 Andrew/Joe/Sven의 솔루션보다 느린 속도의 순서를 발견했습니다. Joe의 솔루션은 100,000 개의 요소와 많은 시작점과 끝점을 가진 배열에서 작동하며 40 배를 약간 넘는 속도로 실행되었습니다. – Abiel

+0

@Abiel : 의견에 많은 감사를드립니다. 때때로 이러한 게시물을 쓰는 것은 많은 작업입니다. 누군가 그것을 보았다는 것을 알면 그만한 가치있는 노력이 생깁니다. – dawg

관련 문제