最大でd個の不一致があるすべての順列を生成します
Aug 20 2020
DNA配列のハミング距離がdまでのパターンマッチングの問題を解決していました。正規表現は私をそこに救いました。しかし今、私は別の問題に遭遇しました。長いDNA配列を考えると、最大でd個のミスマッチを持つ最も頻繁なミスマッチk-merを見つける必要があります。ここで、k-merは長さkのサブシーケンスを指します。
注: DNA配列は、{A、C、G、T}の4文字のみを使用して表すことができます。
例えば、
DNA sequence= "AGGC"
k = 3
d = 1
ここでは、「AGG」、「GGC」の2つのk-merのみが可能です。
これで、「AGG」と「GGC」の次のコードを実行することで、1つの不一致で個別に並べ替えることができます。
def permute_one_nucleotide(motif, alphabet={"A", "C", "G", "T"}):
import itertools
return list(
set(
itertools.chain.from_iterable(
[
[
motif[:pos] + nucleotide + motif[pos + 1 :]
for nucleotide in alphabet
]
for pos in range(len(motif))
]
)
)
)
「AGG」は以下を提供します:
['TGG', 'ATG', 'AGG', 'GGG', 'AGT', 'CGG', 'AGC', 'AGA', 'ACG', 'AAG']
そして、「GCC」は以下を提供します:
['GCC', 'GAC', 'GGT', 'GGA', 'AGC', 'GTC', 'TGC', 'CGC', 'GGG', 'GGC']
次にCounter、最も頻繁なk-merを見つけるために使用できます。ただし、これはd = 1。の場合にのみ機能します。これを一般化する方法はd <= k?
回答
2 SayanDey Aug 20 2020 at 13:24
これは計算コストの高い方法です。しかし、ええ、希望をフェッチする必要があります。ここで行ったことは、hamming dist 1とのすべての不一致を計算してから、前の不一致からham dist 1との新しい不一致を計算し、dまで繰り返します。
import itertools
all_c=set('AGCT')
other = lambda x : list(all_c.difference(x))
def get_changed(sub, i):
return [sub[0:i]+c+sub[i+1:] for c in other(sub[i])]
def get_mismatch(d, setOfMmatch):
if d==0:
return setOfMmatch
newMmatches=[]
for sub in setOfMmatch:
newMmatches.extend(list(map(lambda x : ''.join(x), itertools.chain.from_iterable(([get_changed(sub, i) for i, c in enumerate(sub)])))))
setOfMmatch=setOfMmatch.union(newMmatches)
return get_mismatch(d-1, setOfMmatch)
dna='AGGC'
hamm_dist=1
length=3
list(itertools.chain.from_iterable([get_mismatch(hamm_dist, {dna[i:i+length]}) for i in range(len(dna)-length+1)]))
# without duplicates
# set(itertools.chain.from_iterable([get_mismatch(hamm_dist, {dna[i:i+length]}) for i in range(len(dna)-length+1)]))
ほぼ10〜20倍速いより良いパフォーマンスコードを見つけました
%%time
import itertools, random
from cacheout import Cache
import time
all_c=set('AGCT')
get_other = lambda x : list(all_c.difference(x))
other={}
for c in all_c:
other[c]=get_other(c)
def get_changed(sub, i):
return [sub[0:i]+c+sub[i+1:] for c in other[sub[i]]]
mmatchHash=Cache(maxsize=256*256, ttl=0, timer=time.time, default=None)
def get_mismatch(d, setOfMmatch):
if d==0:
return setOfMmatch
newMmatches=[]
for sub in setOfMmatch:
newMmatches.extend(list(map(lambda x : ''.join(x), itertools.chain.from_iterable(([get_changed(sub, i) for i, c in enumerate(sub)])))))
setOfMmatch=setOfMmatch.union(newMmatches)
if not mmatchHash.get((d-1, str(setOfMmatch)), 0):
mmatchHash.set((d-1, str(setOfMmatch)), get_mismatch(d-1, setOfMmatch))
return mmatchHash.get((d-1, str(setOfMmatch)))
length_of_DNA=1000
dna=''.join(random.choices('AGCT', k=length_of_DNA))
hamm_dist=4
length=9
len(list(itertools.chain.from_iterable([get_mismatch(hamm_dist, {dna[i:i+length]}) for i in range(len(dna)-length+1)])))
# set(itertools.chain.from_iterable([get_mismatch(hamm_dist, {dna[i:i+length]}) for i in range(len(dna)-length+1)]))
CPU時間:ユーザー1分32秒、システム:1.81秒、合計:1分34秒壁時間:1分34秒