提问人:JuanMacD 提问时间:11/7/2023 最后编辑:JuanMacD 更新时间:11/7/2023 访问量:73
关于 Python 函数以及如何用不同索引替换多个字符的建议
Advice regarding a Python function and how to replace multiple characters with different indexs
问:
我最近回到了 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”] 应返回 ['NNA', 'CNN', 'NGN']
[“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 循环中的逻辑,以及我如何使用 replace。
此示例的当前输出如下: 。如果我没记错的话,它是将“N”的每个实例替换为可用列表“b”的第一个实例。这就是为什么有两个 A 和两个 C',而不是一个带有“AC”的序列和另一个带有“TG”的序列。["ACN", "TGT", "NNG"]
['AAG' 'ACT' 'CCG' 'TGT']
我真的不确定如何解决它,任何帮助都是值得赞赏的!如果需要更多信息,请告诉我。
提前致谢,
答:
你可以试试(注意:根据你的陈述,不应该从不同的序列中混合,所以不应该返回?["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_merge = 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_merge = False
if should_merge:
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']
评论
["ACN", "TNT", "NNG"]
["NNA", "CNN", "NGN"]
["CGA"]