2017-03-04 2 views
1

는 다음 코드다중 처리 모듈을 사용하여 목록을 반복하고 사전의 키와 일치시키는 방법?

infile= open(sys.argv[1], "r") 
lines = infile.readlines()[1:] 
master_lst = ["read"] 
for line in lines: 
line= line.strip().split(',') 
fourth_field = line [3] 
master_lst.append(fourth_field) 

이 마스터 목록이 시퀀스의 고유 한 집합이를 사용하여 CSV 파일에서 생성 master_lst라는 이름의 목록을 가지고있다. 이제 마스터 목록에서 각 시퀀스의 발생 횟수를 계산하기 위해 30 개의 축소 된 FASTA 파일을 루프해야합니다. 30 개 파일의 파일 형식은 다음과 같다 : 발생 횟수를 카운트

>AAAAAAAAAAAAAAA 
7451 
>AAAAAAAAAAAAAAAA 
4133 
>AAAAAAAAAAAAAAAAA 
2783 

, 나는 30 파일의 각을 통해 루프와 키와 값으로 발생 수와 같은 시퀀스 사전을 만들었습니다. 그런 다음 master_lst의 각 요소를 반복하고 이전 단계에서 만든 사전의 키와 일치시킵니다. 일치하는 항목이 있으면 키 값을 새 목록 (ind_lst)에 추가했습니다. 그렇지 않다면 ind_lst에 0을 붙였습니다. 최종 출력은 다음과 같아야합니다 How to append a new list to an existing CSV file?

:

Read       file1  file2 so on until file 30 
AAAAAAAAAAAAAAA     7451  4456 
AAAAAAAAAAAAAAAA    4133  3624 
AAAAAAAAAAAAAAAAA    2783  7012 

for file in files: 
ind_lst = [] 
if file.endswith('.fa'): 
    first = file.split(".") 
    first_field = first [0] 
    ind_lst.append(first_field) 
    fasta= open(file) 
    individual_dict= {} 
    for line in fasta: 
    line= line.strip() 
    if line == '': 
    continue 
    if line.startswith('>'): 
    header = line.lstrip('>') 
    individual_dict[header]= '' 
    else: 
    individual_dict[header] += line 
    for key in master_lst[1:]: 
    a = 0 
    if key in individual_dict.keys(): 
    a = individual_dict[key] 
    else: 
    a = 0 
    ind_lst.append(a) 

가 나는 코드가 여기에서 설명하는 사용하여 CSV 파일로 master_lstind_lst 쓰기 : 그 코드는 다음과 같다

이 코드는 더 작은 master_lst을 사용할 때 완벽하게 작동합니다. 그러나 master_lst의 크기가 커지면 실행 시간이 너무 길어집니다. 현재 작업하고있는 master_lst에는 35,718,501 개의 시퀀스 (요소)가 있습니다. 50 시퀀스를 부분 집합하고 코드를 실행하면 스크립트를 실행하는 데 2 ​​시간이 걸립니다. 따라서 35,718,501 시퀀스의 경우 완료하는 데 영원히 걸릴 것입니다.

이제 스크립트 속도를 높이는 방법을 모르겠습니다. 더 짧은 시간에이 스크립트를 실행할 수 있도록 몇 가지 개선 사항이있을 수 있는지 잘 모르겠습니다. 16 개의 CPU 코어를 가진 Linux 서버에서 스크립트를 실행하고 있습니다. top 명령을 사용하면 스크립트가 하나의 CPU 만 사용한다는 것을 알 수 있습니다. 그러나 저는 파이썬 전문가가 아니며 멀티 프로세싱 모듈을 사용하여 사용 가능한 모든 CPU 코어에서 실행되도록 만드는 방법을 모르겠습니다. 나는이 웹 페이지를 확인했다 : Learning Python's Multiprocessing Module.

그러나 무엇이 defif __name__ == '__main__':이어야하는지 잘 모르겠습니다. 또한 함수에 어떤 인수를 전달해야하는지 잘 모르겠습니다. 나는 다음과 같이 인수를 통과하지 않고, 내가 더글라스에서 첫 번째 코드를 시도 오류를 얻고 있었다 :

File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run 

self._target(*self._args, **self._kwargs) 

나는 지난 몇 일 동안이 일하고있다 그리고 내 원하는 출력을 생성에 성공하지 . 누구나 빠르게 실행될 수있는 대체 코드를 제안 할 수 있거나 여러 CPU에서이 코드를 실행하는 방법을 제안 할 수 있다면 정말 멋지게 될 것입니다. 이 문제를 해결할 수있는 도움을 주시면 감사하겠습니다.

답변

1

다음은 다중 처리 버전입니다. ind_lst을 만들 필요가없는 코드에서 사용하는 것과 약간 다른 접근 방식을 사용합니다.

본질의 차이점은 원하는 데이터의 전치를 먼저 생성 한 다음이를 원하는 결과로 바꾸는 것입니다.먼저 생성

Read,file1,file2 
AAAAAAAAAAAAAAA,7451,4456 
AAAAAAAAAAAAAAAA,4133,3624 
AAAAAAAAAAAAAAAAA,2783,7012 

을 : 대신 직접을 생성 말하면

다음

Read,AAAAAAAAAAAAAAA,AAAAAAAAAAAAAAAA,AAAAAAAAAAAAAAAAA 
file1,7451,4133,2783 
file2,4456,3624,7012 

... 및 내장 zip() 기능 수득하여 원하는 것을 이항 체재.

ind_lst을 만들 필요가 없으며 하나의 파일 열에 파일 하나의 행을 만들 수도 있습니다 (더 쉽고 효율적으로 더 적은 노력으로 수행 할 수 있음).

여기에 코드입니다 :

from __future__ import print_function 

import csv 
from functools import partial 
from glob import glob 
from itertools import izip # Python 2 
import operator 
import os 
from multiprocessing import cpu_count, Pool, Queue 
import sys 

def get_master_list(filename): 
    with open(filename, "rb") as csvfile: 
     reader = csv.reader(csvfile) 
     next(reader) # ignore first row 
     sequence_getter = operator.itemgetter(3) # retrieves fourth column of each row 
     return map(sequence_getter, reader) 

def process_fa_file(master_list, filename): 
    fa_dict = {} 
    with open(filename) as fa_file: 
     for line in fa_file: 
      if line and line[0] != '>': 
       fa_dict[sequence] = int(line) 
      elif line: 
       sequence = line[1:-1] 

    get = fa_dict.get # local var to expedite access 
    basename = os.path.basename(os.path.splitext(filename)[0]) 
    return [basename] + [get(key, 0) for key in master_list] 

def process_fa_files(master_list, filenames): 
    pool = Pool(processes=4) # "processes" is the number of worker processes to 
           # use. If processes is None then the number returned 
           # by cpu_count() is used. 
    # Only one argument can be passed to the target function using Pool.map(), 
    # so create a partial to pass first argument, which doesn't vary. 
    results = pool.map(partial(process_fa_file, master_list), filenames) 
    header_row = ['Read'] + master_list 
    return [header_row] + results 

if __name__ == '__main__': 
    master_list = get_master_list('master_list.csv') 

    fa_files_dir = '.' # current directory 
    filenames = glob(os.path.join(fa_files_dir, '*.fa')) 

    data = process_fa_files(master_list, filenames) 

    rows = zip(*data) # transpose 
    with open('output.csv', 'wb') as outfile: 
     writer = csv.writer(outfile) 
     writer.writerows(rows) 

    # show data written to file 
    for row in rows: 
     print(','.join(map(str, row))) 
+0

당신의 시간과 노력에 대한 module.Thank 당신이 너무 많은 다중 처리로 문제를 해결하는 방법을 보여 주셔서 너무 감사드립니다. 이전 스크립트에서 프로파일 링을 사용했지만 정확한 병목 현상을 찾는 방법을 잘 모르겠습니다. 마침내 발견했을 때, 문제가되었던 for 루프 다음에 if 문이있었습니다. 나는 판다 데이터 프레임 (다중 처리없이)을 사용하여 다른 해결책을 시도했다. 나는 내 문제를 해결하기 위해 좀 더 가까웠고 대답도 얻었다. 고마워요. 저는 최근에 파이썬을 배우기 시작한 생물 학자입니다 만, 스크립트 작성에 대한 여러분의 의견을 확실히 통합 할 것입니다. – rex

+0

여러분 환영합니다. 나는 당신이 생물 정보학에서 일했던 것을 의심하여 ​​손을 빌려 주기로 결정했습니다. 솔직하게 측정 할 실제 데이터 파일이 없기 때문에 멀티 프로세싱을 사용하지 않는 것보다 빠르다는 것을 정말로 알지 못합니다. 또한 마스터 목록이 각 하위 작업에 복사본을 전달하기 때문에 매우 큰 경우 문제가 발생할 수 있습니다. 시작될 때 각 하위 작업을 파일에서 읽게함으로써이 문제를 해결할 수 있습니다. 즉, 귀하의 질문에 대한 답변이 있으면이를 수락하는 것이 좋습니다. [누군가가 내 질문에 대답 할 때 _ _ 무엇을해야합니까? _] (http://url.com/help/someone-answers) – martineau

+0

@rex :이 멀티 프로세싱 방식이 더 빠릅니까? – martineau