2013-11-03 2 views
1

나는 정렬 된 목록을 가지고있다. 실제로 x로 정렬 된 (x, y, z) 트리플의 거대한 배열이다. 내 목표는 x의 범위에 따라 조각으로 나누는 것입니다. 나는 지금은 동안을 잘못했기 때문에 작동하지 않습니다 물론 파이썬 while while while sorted list/array

for triple in hugelist: 
    while triple[0] >= minx and triple[0] < maxx: 
     #do some stuff 
    # when out of that range, increase endpoints to the next range 
    minx = minx + deltax 
    maxx = maxx + deltax 
    # do some other stuff 
    # and hopefully move to next triple 

을하려고했는데, 나는 그 이유를 이해합니다. 그러나 나는 목록을 통해가는 길을 생각할 수 없다. hugelist는 약 600 개의 청크로 분해되는 약 2 백만 개의 트리플입니다. 가능한 한 순서대로 한 번만 전달하기를 바랍니다.

============================== 291 점 미니 목록을 사용하여

팀의 도움으로

, 당신은 단순히 triple[0] 원하는 범위 내에 있는지 확인하는 if을 사용할 수 있습니다

while xstart < len(heights): 
    xfinish = bisect.bisect_left(heights, (maxx, 0, 0), lo=xstart)  
    xslice = heights[xstart:xfinish] 
    print "xstart is ", xstart, " xfinish is ", xfinish 
    print "maxx is ", maxx, " xslice is ", xslice 

    maxx += deltax 
    xstart = xfinish 


xstart is 0 xfinish is 291 
maxx is 804.0 xslice is [(803.01, 1941.84, 0.74) (803.04, 1941.88, 0.45) (803.06, 1941.25, 0.0) 
(803.07, 1941.01, 0.0) (803.07, 1941.52, 0.31) (803.09, 1941.16, 0.08) 
(803.12, 1940.05, 0.0) (803.13, 1939.72, 0.3) (803.13, 1939.86, 0.11) 
(803.13, 1940.29, 0.17) . . . (803.23, 1938.24, 0.2) 
(803.23, 1938.25, 0.45) (803.23, 1938.29, 0.1) (803.23, 1938.36, 0.0) 
(803.23, 1938.49, 0.0) (803.96, 1941.06, 4.21) (**803.98**, 1940.6, 4.55) 
(**804.0**, 1940.32, 4.49) (**804.01**, 1940.68, 4.6) . . . (806.11, 1934.82, 10.64) 
(806.11, 1934.86, 10.65) (806.11, 1934.91, 10.56) (806.32, 1933.24, 4.69)] 
+0

다음과 같이 하시겠습니까? [(1,2,3), (4,5,6)]'또는 다음과 같이 : [1,2,3,4,5,6] – dawg

+0

무엇을 하시겠습니까? 목록을 조각으로 나누면 성취 할 수 있을까요? – Stuart

+0

코드의'# 일부 물건 '부분에서하는 일은 정확히 무엇입니까? Numpy가 @TimPeters에서 제안한 바 이진 검색을 사용하여 슬라이스 끝점을 계산하는 것을 포함하여 전체를 벡터화 할 수있는 기회가 있습니다. 즉 while 루프를 사용하는 것이 최선의 선택이 아님을 의미합니다. – Jaime

답변

1

다음은 목록이 정렬 된 것을 이용하여보다 효율적이고 다른 방법입니다.

from bisect import bisect_left 

istart = 0 
while istart < len(hugelist): 
    ifinish = bisect_left(hugelist, (maxx, 0, 0), lo=istart) 
    # Now work on the slice hugelist[istart:ifinish]. 
    # It's possible that istart == ifinish, i.e. that the 
    # slice is empty! 
    maxx += deltax 
    istart = ifinish 

이진 검색을 사용하면 필요한 비교 횟수가 줄어 듭니다.

편집 : 코멘트에서 :

당신이 왼쪽 요소의 "왼쪽에"0, 사이의 요소를 가리키는으로 목록 인덱스로 생각한다면 그것은 매우 분명하게, 그리고 len(hugelist) " 가장 오른쪽 요소의 오른쪽으로. " 그런 다음 bisect_left()은 첫 번째 요소가> = maxx 인 첫 번째 트리플 바로 앞에 위치를 반환합니다.

예는 정말 도움이 될 것입니다

hugelist = [(0,0,0), (1,0,0), (3,0,0), (4,1,1), (4,2,2), (5,0,0)] 
maxx = 0 
deltax = 1 
istart = 0 
while istart < len(hugelist): 
    ifinish = bisect_left(hugelist, (maxx, 0, 0), lo=istart) 
    # Now work on the slice hugelist[istart:ifinish]. 
    # It's possible that istart == ifinish, i.e. that the 
    # slice is empty! 
    print "for maxx =", maxx, hugelist[istart:ifinish] 
    maxx += deltax 
    istart = ifinish 

그리고 출력 :

for maxx = 0 [] 
for maxx = 1 [(0, 0, 0)] 
for maxx = 2 [(1, 0, 0)] 
for maxx = 3 [] 
for maxx = 4 [(3, 0, 0)] 
for maxx = 5 [(4, 1, 1), (4, 2, 2)] 
for maxx = 6 [(5, 0, 0)] 

대부분 사람들이다 endcases을 보여줍니다 제정신 독자에 대한 ;-)

걱정 것
+0

와우. 아직도 이것을 생각해. 더 간단한리스트를 써야하지만 슬라이스를 분리하면 다른 것을 저장하지 않고도 분산을 잡을 수 있습니다. 감사! –

+0

네, 이렇게하면 훨씬 더 깔끔합니다 :-)리스트 인덱스가 * 요소 사이를 가리키는 것으로 생각하면, 가장 왼쪽 요소가 0 인 "왼쪽으로", "len (휴겔리스트)"가 가장 오른쪽 요소의 오른쪽. 그런 다음 bisect_left()는 첫 번째 요소가> ='maxx' 인 첫 번째 트리플의 직전 위치를 반환합니다. –

+0

그것은 삽입 지점을 지나치게 날려 버립니다. 나는 당신이 쓴 것을 거의 정확히 이해했습니다. >>>는 Xstart

1

: 양분은 MAXX가 가야 할 자리가 없습니다. 내부 루프는 필요 없습니다. 목록이 x 값으로 정렬 된 경우 최소값과 비교할 필요가 없습니다. 단지 그것이 최대 값 이하인지 확인하십시오.

for triple in hugelist: 
    if triple[0] < maxx: 
     #do some stuff 
    else: 
     maxx = maxx + deltax 
     # do some other stuff 

당신이 뭘 하려는지에 따라, 당신은 또한 itertools.groupby으로 보일 수 있습니다.

편집 : groupby을 사용

z_variances = [] 
z_group = [] 
maxx = deltax 
for x, y, z in huge_list: 
    if x < maxx: 
     z_group.append(z) 
    else: 
     z_variances.append(var(z_group)) 
     z_group = [z] 
     maxx += deltax 

또는 : 당신이 코멘트에서 말한대로 목적은, 각 범위 내에서 Z 값의 차이를 얻는 것입니다 경우에 당신은 같은 것을 할 수

z_variances = [] 
for _, group in itertools.groupby(huge_list, lambda x: int(x/deltax)): 
    z_variances.append(var(z for x, y, z in group)) 
+0

드류크 (drewk). –

+0

스튜어트, 각 범위에 대한 z의 분산이 필요합니다. –

+0

제안 된 "if"에 대해 아직도 생각하고 있습니다. . . 나는 그것을 배제했지만, 이제 나는 그 이유를 기억해야합니다! :) –

1

첫째, 샘플 NumPy와 배열 생성 :

>>> alen=300000 
>>> huge=np.arange(alen).reshape(alen/3,3) 
>>> huge 
array([[  0,  1,  2], 
     [  3,  4,  5], 
     [  6,  7,  8], 
     ..., 
     [299991, 299992, 299993], 
     [299994, 299995, 299996], 
     [299997, 299998, 299999]]) 

이 구문은 당신에게 처음을 줄 것이다 열 :

>>> huge[:,0] 
array([  0,  3,  6, ..., 299991, 299994, 299997]) 

당신이 하위 배열이 정렬됩니다 상태 때문에, 당신은 버킷으로 큰 배열을 분리하는 numpy.searchsorted 사용할 수 있습니다.

의이 분에 침입하자

>>> minx=huge[-1][0]/3 
>>> maxx=huge[-1][0]*2/3 
>>> minx 
99999 
>>> maxx 
199998 

그냥 당신이 범위에있는 트리플에 대한 그에 대해 원하는 조건을 테스트 당신이 np.searchsorted 사용하여 원하는 :

>>> np.searchsorted(huge[:,0],[minx,maxx]) 
array([33333, 66666]) 

그런 다음에 huge 슬라이스 원하는 버킷 :

>>> buckets=np.searchsorted(huge[:,0],[minx,maxx]) 
>>> bucket1=huge[0:buckets[0]] 
>>> bucket2=huge[buckets[0]:buckets[1]] 
>>> bucket3=huge[buckets[1]:] 
>>> bucket1 
array([[ 0,  1,  2], 
     [ 3,  4,  5], 
     [ 6,  7,  8], 
     ..., 
     [99990, 99991, 99992], 
     [99993, 99994, 99995], 
     [99996, 99997, 99998]]) 
>>> bucket2 
array([[ 99999, 100000, 100001], 
     [100002, 100003, 100004], 
     [100005, 100006, 100007], 
     ..., 
     [199989, 199990, 199991], 
     [199992, 199993, 199994], 
     [199995, 199996, 199997]]) 
>>> bucket3 
array([[199998, 199999, 200000], 
     [200001, 200002, 200003], 
     [200004, 200005, 200006], 
     ..., 
     [299991, 299992, 299993], 
     [299994, 299995, 299996], 
     [299997, 299998, 299999]]) 

피.히스토그램 :

>>> edges=np.histogram(huge[:,0],[0,minx,maxx,huge[-1][0]])[1] 
>>> b1=huge[edges[0]:edges[1]] 
>>> b2=huge[edges[1]:edges[2]] 
>>> b3=huge[edges[2]:edges[3]] 
0

그냥 "X까지", itertools.takewhile 사용하려면 : 당신이 전체 수집을 위해 그룹을 지정하려면

import itertools 

li = [(1,2,3),(4,5,6),(7,8,9),(10,11,12),(13,14,15)] 

list(itertools.takewhile(lambda x: x[0] < 10,li)) 
Out[78]: [(1, 2, 3), (4, 5, 6), (7, 8, 9)] 

를, 그것의 itertools.groupby :

def grouper(x): 
    if x < 5: 
     return 0 
    if x < 11: 
     return 1 
    return 2 

for i,g in itertools.groupby(li,lambda x: grouper(x[0])): 
    print('group {}: {}'.format(i,list(g))) 

group 0: [(1, 2, 3), (4, 5, 6)] 
group 1: [(7, 8, 9), (10, 11, 12)] 
group 2: [(13, 14, 15)] 
+0

'numpy' 태그가 붙은 것으로 나타났습니다. 귀하의 데이터가 실제로 numpy 배열에 있습니까? 이 대답은 numpy에게는 부적합합니다.(이것이 왜 샘플 데이터를 제공해야하는지) – roippi

+0

예, 미안하지만, 반드시 그렇지는 않습니다 : 목록으로 만들 수 있습니다 –