2017-01-10 1 views
0

이 코드는 샘플 데이터에서 빠르게 실행되지만 큰 파일을 반복 할 때 중첩 된 for 루프 때문에 천천히 실행되는 것처럼 보입니다. 기본값 명령의 항목을 반복하여 반복하는 다른 이유가 있습니까?namedtuple 및 dicts에 대해 정의 된 쌍에 대한 반복 속도가 느림

import itertools 

sample_genes1={"0002":["GENE1", "GENE2", "GENE3", "GENE4"], 
       "0003":["GENE1", "GENE2", "GENE3", "GENE6"], 
       "0202":["GENE4", "GENE2", "GENE1", "GENE7"]} 

def get_common_gene_pairs(genelist): 
    genedict={} 
    for k,v in sample_genes1.items(): 
     listofpairs=[] 
     for i in itertools.combinations(v,2): 
      listofpairs.append(i) 
      genedict[k]=listofpairs 
    return genedict 

from collections import namedtuple,defaultdict 
def get_gene_pair_pids(genelist): 
    i=defaultdict(list) 
    d=get_common_gene_pairs(sample_genes1) 
    Pub_genes=namedtuple("pair", ["gene1", "gene2"]) 
    for p_id,genepairs in d.iteritems(): 
     for p in genepairs: 
      thispair=Pub_genes(p[0], p[1]) 
      if thispair in i.keys(): 
       i[thispair].append(p_id) 
      else: 
       i[thispair]=[p_id,] 
    return i 

if __name__=="__main__": 
    get_gene_pair_pids(sample_genes1) 
+0

이와 같은 문제를 해결하기 위해 가장 먼저해야 할 일 중 하나는 코드를 프로파일하는 것입니다. # [Python 스크립트를 프로파일 링 할 수 있습니까? _] (http://stackoverflow.com/questions/582336/how-can-you-profile-a-python-script)를 보면 얼마나 쉬운 지 알 수 있습니다. – martineau

답변

2

하나의 큰 문제 :이 라인 :

if thispair in i.keys(): 

사전 검색을 활용하지 않습니다, 그것은 선형 검색합니다. 이에 의해

if thispair in i.keys(): 
    i[thispair].append(p_id) # i is defaultdict: even if thispair isn't in the dict, it will create a list and append p_id. 
else: 
    i[thispair]=[p_id,] 

:

if thispair in i: 

하지만 i 이후

이 키가 존재하지 않는 경우, 바로 교체하십시오 list를 생성하는 기본 딕셔너리입니다 : 사전이 빠른 조회를하자의 keys() 전화를 드롭 간단한 문장 :

i[thispair].append(p_id) 

(p_id의 한 해시 거기에 있기 때문에 더 빨리이다)

을 요약합니다 :

  • thispair in i.keys()을하지 않는다 : 그것은 defaultdict 여부
  • 당신이 defaultdict 정의하지만, 코드가 단지 dict 가정, 파이썬 2, 느린, 또는 3 , 그러나 느리게 작동합니다.

참고 : 단순한 dict으로 .keys()를 제거하거나이를 할 수 있었다 defaultdict없이 :

i.setdefault(thispair,list) 
i[thispair].append(p_id) 

(여기서 기본 항목은 키에 따라 다름)을 제외하고

:

def get_common_gene_pairs(genelist): 
    genedict={} 
    for k,v in sample_genes1.items(): # should be genelist, not the global variable, you're not using the genelist parameter at all 

그리고 값을 사용하고 있지 않습니다. ues of sample_genes1. 그것이 목록 comprhension 카운터 부분에 비해 섭취하는 훨씬 더 많은 시간을 것입니다

def get_common_gene_pairs(genelist): 
    return {k : list(itertools.combinations(v,2)) for k,v in genelist.items()} 

list.append을() :

+0

완벽하게 설명되었습니다. 만약'if' 조회를 건너 뛰기 위해'setdefault'의 사용을 언급 할 수 있다면 멋질 것입니다. –

+0

'defaultdict' 권한을 사용하지 않는다면 의미할까요? –

+0

신경 쓰지 마세요. OP는'defaultdict' *에 대해 알고 있기 때문에 쓸모가 없다고 생각합니다. 그냥 'defaultdict'의 올바른 사용을 언급하면 ​​여기에 충분합니다 –

1

Jean's answer에 추가하여 get_common_gene_pairs 함수는 다음과 같이 DICT 이해를 사용하여 최적화 할 수 . 또한 목록으로 변환하려면 itertools.combinations(v,2) 이상을 반복 할 필요가 없습니다. 타입 캐스팅을 list으로하면됩니다. 당신이 모양을 복용에 관심이있는 경우에 여기

, 나는 Comparing list comprehensions and explicit loops에 대답 지능형리스트list.append() 사이의 비교입니다.

+0

위대한! 나는 왜 내가 어떤 방식으로 일을해야하는지에 대한 이론적 근거에 대해 더 많이 배우는 것을 좋아한다. 정말 고마워. 내 레퍼토리에 목록을 추가하는 작업을 할 것입니다. – user3089348