有关 Python 函数以及如何用不同索引替换多个字符的建议

问题描述 投票:0回答:1

我最近又回到了Python,我需要一些帮助来解决这个问题:

我有等长的DNA序列,其中一些里面有N(错误)。我需要一个脚本,用其他序列中的可用核苷酸替换一个序列中的 N。因此,只有当用作输入的所有序列在一个位置上都有 N 时,输出才会有 N。 另外,如果一个序列有 N,但其他两个序列有,例如 A 和 T,则应该有两个输出:一个包含一个选项,另一个包含另一个选项。

但这并不意味着我需要所有可能的组合(那样会更容易)。脚本应该“坚持”一个序列中的一组选项,而不是将每种可能性都作为输出。

以下是一些输入和预期输出作为示例:

  1. [“ATC”,“CGN”,“NNN”]应返回[ATC,CGC]

  2. [“ACG”,“TGT”,“CAG”]应返回[“ACG”,“TGT”,“CAG”]

  3. [“ATN”,“GCN”,“GGN”]应返回[“ATN”,“GCN”,“GGN”]

到目前为止,上面的所有示例都适用于我的代码。

但是我在使这些示例正常工作时遇到一些问题:

  1. [“ACN”,“TGT”,“NNG”]应返回['ACT','TGG','ACG','TGT']

  2. [“NTA”,“GNC”,“CGN”]应返回[“GTA”,“CTA”,“GGC”,“GTC”,“CGA”]

  3. [“NNA”、“CNN”、“NGN”] 应返回 [“CGA”]

  4. [“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”的序列。

我不太确定如何解决它,非常感谢任何帮助!如果需要更多信息,请告诉我。

提前致谢,

python string replace bioinformatics
1个回答
0
投票

你可以尝试(注意:根据你的说法,不应该混合不同的序列,所以

["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']
© www.soinside.com 2019 - 2024. All rights reserved.