Python 计算字符串中两个字母对的最快方法

Python 计算字符串中两个字母对的最快方法,python,string,performance,numpy,list-comprehension,Python,String,Performance,Numpy,List Comprehension,计算字符串中两个字母对的数量(即AA、AB、AC等)的最快方法是什么?是否可以使用numpy来加速此计算 我将列表理解与str.count()结合使用,但速度相当慢 import itertools seq = 'MRNLAIIPARSGSKGLKDKNIKLLSGKPLLAYTIEAARESGLFGEIMVSTDSQEYAD'\ 'IAKQWGANVPFLRSNELSNDTASSWDVVKEVIEGYKNLGTEFDTVVLLQPTSPLRTS'\ 'IEGYKIMK

计算字符串中两个字母对的数量(即AA、AB、AC等)的最快方法是什么?是否可以使用numpy来加速此计算

我将列表理解与
str.count()
结合使用,但速度相当慢

import itertools

seq = 'MRNLAIIPARSGSKGLKDKNIKLLSGKPLLAYTIEAARESGLFGEIMVSTDSQEYAD'\
      'IAKQWGANVPFLRSNELSNDTASSWDVVKEVIEGYKNLGTEFDTVVLLQPTSPLRTS'\
      'IEGYKIMKEKDANFVVGVCEMDHSPLWANTLPEDLSMENFIRPEVVKMPRQSIPTYY'\
      'RINGALYIVKVDYLMRTSDIYGERSIASVMRKENSIDIDNQMDFTIAEVLISERSKK'

chars = list('ACDEFGHIKLMNPQRSTVWY')
pairs = [''.join(pair) for pair in itertools.product(chars, chars)]
print(pairs[:10])
print(len(pairs))

['AA', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AK', 'AL']
400

%timeit counts = np.array([seq.count(pair) for pair in pairs])
231 µs ± 5.88 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

print counts[:10]
[0, 1, 1, 0, 0, 0, 1, 1, 1, 0]

有一个numpy函数,
np.char.count()
。但它似乎比str.count()慢得多


如果您不介意在字典中获取计数,则集合中的计数器类的处理速度将加快2-3倍:

from collections import Counter
chars  = set('ACDEFGHIKLMNPQRSTVWY')
counts = Counter( a+b for a,b in zip(seq,seq[1:]) if a in chars and b in chars)

print(counts)
Counter({'RS': 4, 'VV': 4, 'SI': 4, 'MR': 3, 'SG': 3, 'LL': 3, 'LS': 3, 
         'PL': 3, 'IE': 3, 'DI': 3, 'IA': 3, 'AN': 3, 'VK': 3, 'KE': 3, 
         'EV': 3, 'TS': 3, 'NL': 2, 'LA': 2, 'IP': 2, 'AR': 2, 'SK': 2, 
         ...
这种方法将正确计算重复3次或更多次的相同字符的序列(即,“WWW”将作为“WW”的2计,而seq.count()或re.findall()将仅计算1)

请记住,计数器字典将为counts['LC']返回零,但counts.items()不会包含'LC'或字符串中实际不包含的任何其他对

如果需要,您可以在第二步中获得所有理论对的计数:

from itertools import product
chars = 'ACDEFGHIKLMNPQRSTVWY'
print([counts[a+b] for a,b in product(chars,chars)][:10])
[1, 0, 1, 1, 0, 0, 0, 1, 1, 1]

由于速度至关重要,以下是不同方法的比较:

import numpy as np
import itertools
from collections import Counter

seq = 'MRNLAIIPARSGSKGLKDKNIKLLSGKPLLAYTIEAARESGLFGEIMVSTDSQEYAD'\
      'IAKQWGANVPFLRSNELSNDTASSWDVVKEVIEGYKNLGTEFDTVVLLQPTSPLRTS'\
      'IEGYKIMKEKDANFVVGVCEMDHSPLWANTLPEDLSMENFIRPEVVKMPRQSIPTYY'\
      'RINGALYIVKVDYLMRTSDIYGERSIASVMRKENSIDIDNQMDFTIAEVLISERSKK'

chars = list('ACDEFGHIKLMNPQRSTVWY')
pairs = [''.join(pair) for pair in itertools.product(chars, chars)]


def countpairs1():
    return np.array([seq.count(pair) for pair in pairs])

%timeit counts = countpairs1()
144 µs ± 1.02 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)


def countpairs2():
    counted = Counter(a+b for a,b in zip(seq,seq[1:]))
    return np.array([counted[pair] for pair in pairs])

%timeit counts = countpairs2()
102 µs ± 729 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)


def countpairs3():
    return np.array([np.char.count(seq, pair) for pair in pairs])

%timeit counts = countpairs3()
1.65 ms ± 4.62 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

显然,最好/最快的方法是
计数器

谢谢
计数器
比str.count稍快(196µs对231µs)。另外,另一种方法对3个或更多重复字母序列的对数进行错误计数(即计数器将正确返回2x'AA'表示“AAA”,而其他两种方法将返回1x'AA')
import numpy as np
import itertools
from collections import Counter

seq = 'MRNLAIIPARSGSKGLKDKNIKLLSGKPLLAYTIEAARESGLFGEIMVSTDSQEYAD'\
      'IAKQWGANVPFLRSNELSNDTASSWDVVKEVIEGYKNLGTEFDTVVLLQPTSPLRTS'\
      'IEGYKIMKEKDANFVVGVCEMDHSPLWANTLPEDLSMENFIRPEVVKMPRQSIPTYY'\
      'RINGALYIVKVDYLMRTSDIYGERSIASVMRKENSIDIDNQMDFTIAEVLISERSKK'

chars = list('ACDEFGHIKLMNPQRSTVWY')
pairs = [''.join(pair) for pair in itertools.product(chars, chars)]


def countpairs1():
    return np.array([seq.count(pair) for pair in pairs])

%timeit counts = countpairs1()
144 µs ± 1.02 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)


def countpairs2():
    counted = Counter(a+b for a,b in zip(seq,seq[1:]))
    return np.array([counted[pair] for pair in pairs])

%timeit counts = countpairs2()
102 µs ± 729 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)


def countpairs3():
    return np.array([np.char.count(seq, pair) for pair in pairs])

%timeit counts = countpairs3()
1.65 ms ± 4.62 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)