私は与えられた配列のヌクレオチドを数え、結果をリストに返すという、Rosalindの基本的な問題を解決しようとしています。バイオインフォマティクスに精通していない人にとっては、文字列内の4つの異なる文字( 'A'、 'C'、 'G'、 'T')の出現回数を数えるだけです。なぜCollections.counterが遅いのですか?
私はcollections.Counter
が最も高速な方法であると予想していました(最初は高性能であると主張していたため、2番目はこの特定の問題で使用していました)。
しかし、私の驚きにはこの方法は最も遅いです!短い配列に多くの時間を実行している長いシーケンスを数回
- : 私は
timeit
を使用し、2つの実験の種類を実行している、3つの異なる方法を比較しました。ここで
が私のコードです:
import timeit
from collections import Counter
# Method1: using count
def method1(seq):
return [seq.count('A'), seq.count('C'), seq.count('G'), seq.count('T')]
# method 2: using a loop
def method2(seq):
r = [0, 0, 0, 0]
for i in seq:
if i == 'A':
r[0] += 1
elif i == 'C':
r[1] += 1
elif i == 'G':
r[2] += 1
else:
r[3] += 1
return r
# method 3: using Collections.counter
def method3(seq):
counter = Counter(seq)
return [counter['A'], counter['C'], counter['G'], counter['T']]
if __name__ == '__main__':
# Long dummy sequence
long_seq = 'ACAGCATGCA' * 10000000
# Short dummy sequence
short_seq = 'ACAGCATGCA' * 1000
# Test 1: Running a long sequence once
print timeit.timeit("method1(long_seq)", setup='from __main__ import method1, long_seq', number=1)
print timeit.timeit("method2(long_seq)", setup='from __main__ import method2, long_seq', number=1)
print timeit.timeit("method3(long_seq)", setup='from __main__ import method3, long_seq', number=1)
# Test2: Running a short sequence lots of times
print timeit.timeit("method1(short_seq)", setup='from __main__ import method1, short_seq', number=10000)
print timeit.timeit("method2(short_seq)", setup='from __main__ import method2, short_seq', number=10000)
print timeit.timeit("method3(short_seq)", setup='from __main__ import method3, short_seq', number=10000)
結果:
Test1:
Method1: 0.224009990692
Method2: 13.7929501534
Method3: 18.9483819008
Test2:
Method1: 0.224207878113
Method2: 13.8520510197
Method3: 18.9861831665
方法1 方法速く方法2との両方の実験のための3以上です!
だから私は、一連の質問している:
は、私が何か間違ったことをやっているか、それは確かに他の二つのアプローチより遅いのですか?誰かが同じコードを実行して結果を共有できますか?
私の結果が正しい場合(そしてこれは別の質問かもしれません)、方法1を使用するよりもこの問題を解決する方が速いのですか?
count
が高速の場合、collections.Counter
とは何ですか?collections.Counter
が遅いので
これは本当に面白いです。最初のメソッドをわずかに変更し、シーケンスの 'len'から" A "、" C "、" G "を引いたものでなければならないので、最後のメソッド(" T ")はカウントしません。私もそれを実行するつもりです –
Test1:{方法1:0.24、方法2:19.73、方法3:4.63} テスト2:{方法1:0.26、方法2:19.35、方法3:4.30}。少なくとも「カウンタ」はメソッド2より速く、悪意のあるコードではありません。 –
驚くべきことはありません。方法1では、非常にシンプルなCコードでさえ、Cコードを使用します。そしてあなたはそれを4回しかやっていません。それははるかに速いのは不思議ではない –