これは、それを行うための最速の方法を見つけることです。別の行に約100万個の文字列(長さ6〜40)を含むfile1があります。約 80,000 個の文字列を含む別の file2 でそれらのそれぞれを検索し、出現回数をカウントします (1 つの文字列で小さな文字列が複数回見つかった場合、この文字列の出現回数は 1 のままです)。パフォーマンスの比較に興味がある人は、file1 と file2 をダウンロードするためのリンクがあります。dropbox.com/sh/oj62918p83h8kus/sY2WejWmhu?m
私が今行っているのは、ファイル 2 の辞書を作成し、文字列 ID をキーとして、文字列を値として使用することです。(file2 の文字列は値が重複しているため、文字列 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))))
私のコードは完了するまでに数時間かかります。誰でもそれを行うためのより速い方法を提案できますか? file1 と file2 はどちらも約 50M です。私の PC には 8G のメモリがあり、高速化するために必要なだけメモリを使用できます。1時間で終わる方法ならなんでもOKです:)
ここで、以下のコメントからいくつかの提案を試した後、パフォーマンスの比較を参照してください。最初にコードが来て、次に実行時間です。
Mark 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()
完了するまでに 1m4 秒かかります。私の古いものと比較して改善された20代
#######エントロピーが提案する次の方法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()
これには 1 分 10 秒かかりますが、重複の検索を回避するため、期待したほど速くはありません。理由がわかりません。
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()
完了するのに 0 分 11 秒しかかからず、他の方法よりもはるかに高速です。しかし、カウント結果をすべて0にするのは私のミスなのか、マークの方法に欠陥があるのか わかりません。