0

因此,该程序工作得很好,但即使在合并了 abarnert 建议的最后修改之后,它仍然不能确保生成一个独特的突变。

这就是我到目前为止所得到的。肯定是不对的,但是我不完全明白python是如何执行下面abarnert写的代码的。

a = open (scgenome, 'r')

codon = [ ] 

for line in a:

    data=line.split("\t") 

    codon.append(data[12]) 

import random 

def string_replace(s,index,char):
    return s[:index] + char + s[index+1:]


for x in range(1,1000):
   index = random.randrange(3)
   letter_to_replace = random.choice(list({"A", "G", "T", "C"} - {codon[index]}))
   mutated_codon = [string_replace(codon[x], index, letter_to_replace)]
       for c in mutated_codon: 
             codon_lookup[c]

我也尝试在不使用范围的情况下以您的方式编写此代码,尽管我喜欢使用范围函数,以便我可以打印出 10 或 100 个密码子并手动检查输出是否正确,但随后我得到一个 Keyerror: 'r',在尝试确保每个替换都是唯一的之前,当我运行这个程序之前没有发生这种情况:

def string_replace(s,index,char):

    return s[:index] + char + s[index+1:]



def mutate_codon(codon):

  index = random.randrange(3)

  letter_to_replace = random.choice(list({"A", "G", "T", "C"} - {codon[index]}))

  return string_replace(codon, index, letter_to_replace)



 for codon in codons:
   codons = mutate_codon(codon)

   print codons 

   for c in codons:

      codon_lookup[c]

      if codon_lookup[c] == ref_aminoacid[x]:

           print codons, "\t", codon_lookup[c]

      else: 

          print codons, "\t", codon_lookup[c]
4

1 回答 1

5

该函数random.choice从序列中选择一个随机元素。所以:

letter_to_replace = random.choice(['A', 'C', 'G', 'T'])

要从给定的密码子中选择一个字母,您真的想随机选择一个索引- 0、1 或 2。(毕竟,对于密码子'AAA',您可能希望能够替换三个'A'字符中的任何一个,对吗? ) 为此,请使用random.randrange(3)

for codon in codons:
    index_to_replace = random.randrange(3)
    codon[index_to_replace] = letter_to_replace

除了如果 eachcodon是一个字符串,当然,你不能就地改变它,所以你需要一个这样的函数:

def string_replace(s, index, char):
    return s[:index] + char + s[index+1:]

我们在这里所做的是从切片中构建一个新字符串:s[:index]是从开头到第indexth 的所有字符(请记住,Python 切片是半开的:s[i:j]包括i, i+1, ..., j-1,但不包括j),并且s[index+1]是所有的从index+1th 到结尾的字符。所以,这是之前的一切indexchar代替之前的一切index,然后是之后的一切index。这在本教程的字符串部分中有详细描述(在同一章的列表部分中进行了一些后续操作)。

虽然你已经在做一成不变的事情:

codons = [string_replace(codon, random.randrange(3), letter_to_replace)
          for codon in codons]

这使用了列表推导:我们没有就地修改密码子列表,而是构建了一个新的密码子列表。教程中的List Comprehensions解释了这些是如何工作的,但一个简单的示例可能会有所帮助:

a = [1, 2, 3, 4]
b = [2 * element for element in a]
assert b == [2, 4, 6, 8]

c = []
for element in a:
    c.append(2 * element)
assert c == b

您还可以在使用子句构建列表时过滤列表,将if多个子句嵌套for在一起,构建setordict或惰性生成器,而不是list...有关完整详细信息,请参阅文档


以下是如何将它们放在一起,以及其他一些修复(使用 awith确保文件被关闭,以及我对这个问题发表评论的一些内容):

# Read the codons into a list
with open(scgenome) as f:
    codons = [line.split('\t')[12] for line in f]

# Create a new list of mutated codons
def string_replace(s, index, char):
    return s[:index] + char + s[index+1:]
letter_to_replace = random.choice(['A', 'C', 'G', 'T'])
codons = [string_replace(codon, random.randrange(3), letter_to_replace)
          for codon in codons]

如果您想保证每个密码子中的单点突变,并且您不需要每个密码子都突变为相同的碱基,那么您需要重新考虑一下。对于每个密码子,选择三个位置之一。然后,不要从所有四个基地中随机选择,而是从所有基地中选择,除了已经存在的基地。所以:

def string_replace(s, index, char):
    return s[:index] + char + s[index+1:]

def mutate_codon(codon):
    index = random.randrange(3)        
    new_base = random.choice(list({'A', 'C', 'T', 'G'} - {codon[index]}))
    return string_replace(codon, index, new_base)

codons = [mutate_codon(codon) for codon in codons]

如果该函数行令人困惑,让我解释一下:集合有一个很好的-运算符来计算集合的差异——也就是说,左侧集合中的所有值都不在右侧集合中。{'A', 'C', 'T', 'G'} - {'T'}{'A', 'C', 'G'}。所以,我取所有四个碱基的集合,减去已经在 的那个codon[index],然后随机选择其他三个中的任何一个。由于choice仅适用于序列,因此我必须从集合中列出一个列表。

当然,您可以首先将其重写为使用列表(甚至是 str),但是您必须手动编写“列表差异”。没有大碍:

new_base = random.choice([base for base in codon if base != codon[index]])
于 2013-11-04T19:27:02.933 回答