2017-09-13 2 views
0

저는 파이썬에 익숙하지 않지만,해야 할 일이 있습니다. ASCII 파일 (공백으로 구분)이 여러 열로 있습니다. 첫 번째 열에서 일부 값은 중복됩니다. 이 중복 된 값에서 예를 들어 3 열에서 더 큰 값을 가진 선을 선택하고 다시 배열을 반환해야합니다. 여기에 지금까지 가지고 무엇파이썬은 열의 최대 값을 기준으로 행을 선택합니다.

#col1 col2 col3 col4 col5 
1   1  2  3  4 
1   2  1  5  3 
2   2  5  2  1 

선 1, 3 을 반환 : 나는 이런 식으로 뭔가를하고 싶습니다 내가 중복의 인덱스 (모든 두 번째 항목)

을 감지 할 수있는 보조 기능을 정의 다음
def list_duplicates(seq): 
    seen = set() 
    seen_add = seen.add 
    return [idx for idx,item in enumerate(seq) if item in seen or seen_add(item)] 

와 (나는 각 열을 명명 np.genfromtxt있는 파일에서로드 것을) 목록을 읽고 그것을 사용하려고

def select_high(ndarray, dup_col, sel_col): #dup_col is the column where the duplicates are, sel_col is the column where we select the larger value 
    result = [] 
    dup = list_duplicates(ndarray[dup_col]) 
    dupdup = [x-1 for x in dup] 
    for i in range(len(ndarray[sel_col])):   
     if i in dup: 
      mid = [] 
      maxi = max(ndarray[sel_col][i], ndarray[sel_col][i-1]) 
      maxi_index = np.where(ndarray[sel_col] == maxi)[0][0] 
      for name in ndarray.dtype.names: 
       mid.append(ndarray[name][maxi_index]) 
      result.append(mid) 
     else: 
      mid = [] 
      if i not in dupdup: 
       for name in ndarray.dtype.names: 
        mid.append(ndarray[name][i]) 
      result.append(mid) 

    return np.asarray(result) 

하지만, 무슨 일이 일어나고 있는지 중복이있을 때마다 else 부분을 제거해야합니다. 그렇지 않으면 오류가 발생하고 복제본이 없을 때마다 다시 넣어야합니다. 도움이 되시길 바랍니다. 긴 게시물에 대해 유감스럽게 생각합니다. 나는 내 자신을 분명히하기를 희망합니다.

+0

이 결과는'col3'의 경우해야 우리가 이러한 항목이됩니다 :'1,2,3,2,1,4를, 5'? 그것은 min 요소보다 큰 모든 항목이어야합니까? – AndMar

+0

질문에 표시되는 오류를 추가 할 수 있습니까?디버깅이 훨씬 쉬워집니다. – mfitzp

답변

0

나는 당신이 세부 사항에서 (그리고 나도) 잃어버린 것 같아요.

m = [[1, 2, 1, 5, 3], [1, 1, 2, 3, 4], [2, 2, 5, 2, 1]] 
s = sorted(m, key=lambda r:(r[0], -r[2])) 
print(s) 
seen = set() 
print([r for r in s if r[0] not in seen and not seen.add(r[0])]) 

첫 번째 라인은이 파일에서 얻을 행의 목록으로 m을 정의 : 여기 당신이 원하는 것을, 그러나 더 간단하다 버전입니다.

번째 줄은 세 번째 열에있는 값을, 제 1 열 (r[0])의 값에 해당 행 정렬하지만, 작은 값 (-r[2])에 큰 발 :

s=[[1, 1, 2, 3, 4], [1, 2, 1, 5, 3], [2, 2, 5, 2, 1]] 

지금 첫 번째 열의 값을 한 번 이상 본 경우 행을 건너 뛸 필요가 있습니다. 우리는 이미 본 r[0] 값을 저장하기 위해 seen 세트를 사용합니다. r[0]seen이 아닌 경우 행을 유지하고 다음에 r[0]이 표시 될 때 행을 삭제하는 방식으로 seen에 입력해야합니다. 그건 좀 까다로운 : not seen.add(r[0])이 항상 true입니다

if r[0] not in seen and not seen.add(r[0]) 

하는 것으로, seen.add 반환 None 때문이다. 따라서 : seen에없는

  • r[0] 경우, 우리는 seenr[0]을 넣어 r[0]seen에있는 경우 행을

  • 를 유지, 우리는 false를 반환하고 행을 폐기합니다.

당신은 너무처럼 표현할 수있다 :

if not (r[0] in seen or seen.add(r[0])) 
+0

고마워,이게 효과가있는 것 같아서 생각보다 훨씬 간단 해. 참으로 불필요하게 문제를 복잡하게 만들었습니다. 나는 의사 코드에서 질문을 바꿔야한다고 생각한다. – bernie

+0

@bernie 당신은 높은 수준의 언어 인 Python을 사용하고있다 : 낮은 수준의 관심사로 프로그램을 복잡하게하는 것을 피하기 위해서는 약간의 연습이 필요하다. 말하자면, 내 코드는 일종의 의미를 가지며 예상했던 것보다 느릴 수 있습니다 (* O (n) n *) 가능한 O * (n) * 시간의 복잡성). – jferard

관련 문제