生成至多 d 不匹配的所有排列
Generate all Permutations with at most d Mismatches
我正在解决一个 DNA 序列汉明距离最大为 d 的模式匹配问题。正则表达式在那里救了我。但现在我遇到了一个不同的问题。给定一个长 DNA 序列,我必须找到最常见的错配 k-mer,最多有 d 个错配。这里k-mer指的是长度为k的子序列。
注:DNA序列只用四个字母即可表示:{A,C,G,T}
例如,
DNA sequence= "AGGC"
k = 3
d = 1
这里,只有两个 k-mers 是可能的:“AGG”、“GGC”
现在,我可以通过 运行 按照“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
?
这是一种计算量大的方法。但是,是的,应该获取所需的。
我在这里所做的是计算所有与 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秒
我正在解决一个 DNA 序列汉明距离最大为 d 的模式匹配问题。正则表达式在那里救了我。但现在我遇到了一个不同的问题。给定一个长 DNA 序列,我必须找到最常见的错配 k-mer,最多有 d 个错配。这里k-mer指的是长度为k的子序列。
注:DNA序列只用四个字母即可表示:{A,C,G,T}
例如,
DNA sequence= "AGGC"
k = 3
d = 1
这里,只有两个 k-mers 是可能的:“AGG”、“GGC”
现在,我可以通过 运行 按照“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
?
这是一种计算量大的方法。但是,是的,应该获取所需的。 我在这里所做的是计算所有与 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秒