더 빠른 방법을 찾으려합니다. 나는 약 1 백만 개의 문자열 (길이 6-40)을 별도의 줄에 포함하고있는 file1을 가지고있다. 나는 각각 80,000 개의 문자열을 포함하는 파일 2에서 각각을 찾고 싶다. 작은 문자열이 한 번 여러 번 발견되면이 문자열의 발생은 여전히 1이다. 성능 비교에 관심이있는 사용자라면 file1 및 file2를 다운로드 할 수있는 링크가 있습니다. dropbox.com/sh/oj62918p83h8kus/sY2WejWmhu?m파이썬은 파일에서 1 백만 개의 문자열을 검색하고 각 문자열의 수를 계산합니다.
내가 지금하고있는 일은 파일 2에 대한 사전을 구성하고 문자열 ID를 키로 사용하고 문자열을 값으로 사용하는 것입니다. 내 코드는
for line in file1:
substring=line[:-1].split("\t")
for ID in dictionary.keys():
bigstring=dictionary[ID]
IDlist=[]
if bigstring.find(substring)!=-1:
IDlist.append(ID)
output.write("%s\t%s\n" % (substring,str(len(IDlist))))
내 코드가 완료 시간이 걸릴 것입니다 (파일 2에서 문자열 중복 값을 가지고 있기 때문에, 단지 문자열 ID는 고유). 누구든지 빠른 방법을 제안 할 수 있습니까? file1과 file2는 모두 약 50M이며, 내 PC는 8G 메모리를 가지고 있습니다. 더 빨리 만들 필요가있을만큼 많은 메모리를 사용할 수 있습니다. 1 시간 내에 완료 할 수있는 방법은 모두 허용 가능합니다.
아래의 설명에서 몇 가지 제안을 시도한 후 성능 비교를 확인한 후 코드가 실행 시간입니다. 마크 Amery 및 다른 사람
import sys
from Bio import SeqIO
#first I load strings in file2 to a dictionary called var_seq,
var_seq={}
handle=SeqIO.parse(file2,'fasta')
for record in handle:
var_seq[record.id]=str(record.seq)
print len(var_seq) #Here print out 76827, which is the right number. loading file2 to var_seq doesn't take long, about 1 second, you shall not focus here to improve performance
output=open(outputfilename,'w')
icount=0
input1=open(file1,'r')
for line in input1:
icount+=1
row=line[:-1].split("\t")
ensp=row[0] #ensp is just peptides iD
peptide=row[1] #peptides is the substrings i want to search in file2
num=0
for ID,bigstring in var_seq.iteritems():
if peptide in bigstring:
num+=1
newline="%s\t%s\t%s\n" % (ensp,peptide,str(num))
output.write(newline)
if icount%1000==0:
break
input1.close()
handle.close()
output.close()
에 의해 제안
일부 개선이 완료 1m4s를 취할 것입니다. 엔트로피from collections import defaultdict
var_seq=defaultdict(int)
handle=SeqIO.parse(file2,'fasta')
for record in handle:
var_seq[str(record.seq)]+=1
print len(var_seq) # here print out 59502, duplicates are removed, but occurances of duplicates are stored as value
handle.close()
output=open(outputfilename,'w')
icount=0
with open(file1) as fd:
for line in fd:
icount+=1
row=line[:-1].split("\t")
ensp=row[0]
peptide=row[1]
num=0
for varseq,num_occurrences in var_seq.items():
if peptide in varseq:
num+=num_occurrences
newline="%s\t%s\t%s\n" % (ensp,peptide,str(num))
output.write(newline)
if icount%1000==0:
break
output.close()
이 하나의 제안 내 이전
####### 다음의 방법에 비해 개선 된 20 대 빠르지는 중복을 검색 피할 수 있기 때문에 예상대로 이유를 이해하지 않습니다 1m10s 걸립니다. Mark Amery가 제안한 Haystack과 Needle 방법이 가장 빠름이 밝혀졌습니다.이 방법의 문제점은 모든 하위 문자열의 계산 결과가 0이라는 점입니다. 아직 이해할 수 없습니다.다음은 그의 메소드를 구현 한 코드입니다.
class Node(object):
def __init__(self):
self.words = set()
self.links = {}
base = Node()
def search_haystack_tree(needle):
current_node = base
for char in needle:
try:
current_node = current_node.links[char]
except KeyError:
return 0
return len(current_node.words)
input1=open(file1,'r')
needles={}
for line in input1:
row=line[:-1].split("\t")
needles[row[1]]=row[0]
print len(needles)
handle=SeqIO.parse(file2,'fasta')
haystacks={}
for record in handle:
haystacks[record.id]=str(record.seq)
print len(haystacks)
for haystack_id, haystack in haystacks.iteritems(): #should be the same as enumerate(list)
for i in xrange(len(haystack)):
current_node = base
for char in haystack[i:]:
current_node = current_node.links.setdefault(char, Node())
current_node.words.add(haystack_id)
icount=0
output=open(outputfilename,'w')
for needle in needles:
icount+=1
count = search_haystack_tree(needle)
newline="%s\t%s\t%s\n" % (needles[needle],needle,str(count))
output.write(newline)
if icount%1000==0:
break
input1.close()
handle.close()
output.close()
완료하는 데 단지 0m11s 밖에 걸리지 않으며 다른 방법보다 훨씬 빠릅니다. 그러나 모든 계산 결과를 0으로 만드는 것이 내 실수인지 또는 Mark의 방법에 결함이 있는지는 알지 못합니다.
알고리즘을 향상시킬 수있는 방법을 논의하지 않고 PyPy를 사용하여 성능을 향상시킬 수 있습니다. http://pypy.org/ –
string.find() 대신 "in"연산자 사용 - 자바 스크립트 또는 PHP가 아닙니다 –
() –