Я пытаюсь решить основную задачу Rosalind о подсчете нуклеотидов в заданной последовательности и возвращать результаты в списке. Для тех, кто не знаком с биоинформатикой, он просто подсчитывает количество вхождений четырех разных символов ( "A", "C", "G", "T" ) внутри строки.
Я ожидал, что collections.Counter
будет самым быстрым методом (во-первых, потому что они утверждают, что они высокопроизводительны, а во-вторых, потому что я видел много людей, использующих его для этой конкретной проблемы).
Но, к моему удивлению, этот метод является самым медленным!
Я сравнил три разных метода, используя timeit
и выполнив два типа экспериментов:
- Выполнение длинной последовательности несколько раз
- Выполнение короткой последовательности много раз.
Вот мой код:
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
?