我最近又回到了Python,我需要一些帮助来解决这个问题:
我有等长的DNA序列,其中一些里面有N(错误)。我需要一个脚本,用其他序列中的可用核苷酸替换一个序列中的 N。因此,只有当用作输入的所有序列在一个位置上都有 N 时,输出才会有 N。 另外,如果一个序列有 N,但其他两个序列有,例如 A 和 T,则应该有两个输出:一个包含一个选项,另一个包含另一个选项。
但这并不意味着我需要所有可能的组合(那样会更容易)。脚本应该“坚持”一个序列中的一组选项,而不是将每种可能性都作为输出。
以下是一些输入和预期输出作为示例:
[“ATC”,“CGN”,“NNN”]应返回[ATC,CGC]
[“ACG”,“TGT”,“CAG”]应返回[“ACG”,“TGT”,“CAG”]
[“ATN”,“GCN”,“GGN”]应返回[“ATN”,“GCN”,“GGN”]
到目前为止,上面的所有示例都适用于我的代码。
但是我在使这些示例正常工作时遇到一些问题:
[“ACN”,“TGT”,“NNG”]应返回['ACT','TGG','ACG','TGT']
[“NTA”,“GNC”,“CGN”]应返回[“GTA”,“CTA”,“GGC”,“GTC”,“CGA”]
[“NNA”、“CNN”、“NGN”] 应返回 [“CGA”]
[“ACN”,“TNT”,“NNG”]应返回['ACT,''ACG','TCT','ACG']。 TCG 不应该是一个有效的选项,因为“混合”了来自两个不同序列的信息:“ACT”和“TNT”
最后 3 个序列是我的输入中最常见的。 到目前为止,这是我的代码,非常简单:
import numpy as np
def procesar_secuencias(secuencias):
output = []
secuencias_con_n = [s for s in secuencias if 'N' in s] # check if there are N's
if len(secuencias_con_n) == 0: # If there are no N's, simply return the sequences as is
return secuencias
a = [] # positions and nt
b = []
for i in range(len(secuencias)): # for all sequences
for j,k in enumerate(secuencias[i]): # j is position, k is nt
if k != 'N': # if it not an N, save the information
a.append(k)
b.append(j)
for s in secuencias: # for all sequences, ie [ATC, CGN, NNN]
if 'N' in s: # only if s has N's inside
posiciones_n = [i for i, c in enumerate(s) if c == 'N'] # save the position of the N
if len(posiciones_n) == len(s): # if there are only N's, go to the next sequence
break
else:
new_seqs = []
for h in b: # for every "valid" option
for u in posiciones_n: # for all positions that store an N
if h == u: # when there is an available option to change an N for a "valid" nt
new_seq = s.replace(s[h], a[u]) # replace said position for a new nt
new_seqs.append(new_seq)
output.extend(new_seqs)
else:
# If there are no N's, append directly to the output.
output.append(s)
return np.unique(output)
我认为主要问题在于两个 for 循环内部的逻辑,以及我如何使用替换。
此示例的当前输出:
["ACN", "TGT", "NNG"]
是这样的:['AAG' 'ACT' 'CCG' 'TGT']
。如果我没记错的话,它将用列表“b”的第一个可用实例替换“N”的每个实例。这就是为什么有两个 A 和两个 C',而不是一个带有“AC”的序列和另一个带有“TG”的序列。
我不太确定如何解决它,非常感谢任何帮助!如果需要更多信息,请告诉我。
提前致谢,
你可以尝试(注意:根据你的说法,不应该混合不同的序列,所以
["NNA", "CNN", "NGN"]
返回['NNA', 'CNN', 'NGN']
):
test_cases = [
["ATC", "CGN", "NNN"],
["ACG", "TGT", "CAG"],
["ATN", "GCN", "GGN"],
["ACN", "TGT", "NNG"],
["NTA", "GNC", "CGN"],
["NNA", "CNN", "NGN"],
["ACN", "TNT", "NNG"],
]
def process(lst):
lst_indices_N = [{i for i, ch in enumerate(v) if ch == "N"} for v in lst]
lst_indices_non_N = [{i for i, ch in enumerate(v) if ch != "N"} for v in lst]
out = []
for i, v in enumerate(lst_indices_N):
if not v:
out.append(lst[i])
continue
elif v and len(v) == len(lst[i]):
continue
should_add = True
for j, u in enumerate(lst_indices_non_N):
if v.issubset(u):
s = list(lst[i])
for k in v:
s[k] = lst[j][k]
out.append("".join(s))
should_add = False
if should_add:
out.append(lst[i])
return out
for t in test_cases:
print("test case :", t)
print("processed :", process(t))
print()
打印:
test case : ['ATC', 'CGN', 'NNN']
processed : ['ATC', 'CGC']
test case : ['ACG', 'TGT', 'CAG']
processed : ['ACG', 'TGT', 'CAG']
test case : ['ATN', 'GCN', 'GGN']
processed : ['ATN', 'GCN', 'GGN']
test case : ['ACN', 'TGT', 'NNG']
processed : ['ACT', 'ACG', 'TGT', 'ACG', 'TGG']
test case : ['NTA', 'GNC', 'CGN']
processed : ['GTA', 'CTA', 'GTC', 'GGC', 'CGA', 'CGC']
test case : ['NNA', 'CNN', 'NGN']
processed : ['NNA', 'CNN', 'NGN']
test case : ['ACN', 'TNT', 'NNG']
processed : ['ACT', 'ACG', 'TCT', 'ACG']