[英]Processing a sub-list of variable size within a larger list
我是一名生物工程博士生,在这里尝试自学Python程序,用于自动化我的研究的一部分,但我遇到了一个问题,处理更大的列表中的子列表,我似乎无法解决。
基本上,我正在尝试做的目标是编写一个小脚本,处理包含我正在使用各种DNA组装方法构建的质粒序列列表的CSV文件,然后吐出我需要的引物序列为了构建质粒而订购。
这是我正在处理的场景:
当我想构建质粒时,我必须在Excel电子表格中输入该质粒的完整序列。 我必须在两种DNA组装方法中进行选择,称为“Gibson”和“iPCR”。 每个“iPCR”程序集只需要列表中的一行,所以我知道如何处理这些人,因为我只需要在一个单元格中放入我正在尝试构建的质粒的完整序列。 另一方面,“Gibson”组件要求我必须将完整的DNA序列分成更小的块,因此有时我需要在Excel电子表格中2-5行来完整描述一个质粒。
所以我最终得到的电子表格最终看起来像这样:
构建.....战略.....名称
1 ..... Gibson ..... P(OmpC)-cI :: P(cI)-LacZ控制器
1 ..... Gibson ..... P(OmpC)-cI :: P(cI)-LacZ控制器
1 ..... Gibson ..... P(OmpC)-cI :: P(cI)-LacZ控制器
2 ..... iPCR ....... P(cpcG2)-K1F控制器,带K1F位置。 反馈
3 ..... Gibson ..... P(cpcG2)-K1F控制器具有交换的启动子位置
3 ..... Gibson ..... P(cpcG2)-K1F控制器具有交换的启动子位置
4 ..... iPCR ....... P(cpcG2)-K1F控制器具有更强的K1F RBS库
我认为这个长度的清单足够具有代表性。
所以我遇到的问题是,我希望能够遍历列表并处理Gibsons,但我似乎无法让代码按照我想要的方式工作。 这是我到目前为止编写的代码:
#import BioPython Tools
from Bio.Seq import Seq
from Bio.Alphabet import IUPAC
#import csv tools
import csv
import sys
import os
with open('constructs-to-make.csv', 'rU') as constructs:
construct_list = csv.reader(constructs, delimiter=',')
construct_list.next()
construct_number = 1
primer_list = []
temp_list = []
counter = 2
for row in construct_list:
print('Current row is row number ' + str(counter))
print('Current construct number is ' + str(construct_number))
print('Current assembly type is ' + row[1])
if row[1] == "Gibson": #here, we process the Gibson assemblies first
print('Current construct number is: #' + row[0] + ' on row ' + str(counter) + ', which is a Gibson assembly')
## print(int(row[0]))
## print(row[3])
if int(row[0]) == construct_number:
print('Adding DNA sequence from row ' + str(counter) + ' for construct number ' + row[0])
temp_list.append(str(row[3]))
counter += 1
if int(row[0]) > construct_number:
print('Current construct number is ' + str(row[0]) + ', which is greater than the current construct number, ' + str(construct_number))
print('Therefore, going to work on construct number ' + str(construct_number))
for part in temp_list: #process the primer design work here
print('test')
## print(part)
construct_number += 1
temp_list = []
print('Adding DNA from row #' + str(counter) + ' from construct number ' + str(construct_number))
temp_list.append(row)
print('Next construct number is number ' + str(construct_number))
counter += 1
## counter += 1
if str(row[1]) == "iPCR":
print('Current construct number is: ' + row[0] + ' on row ' + str(counter) + ', which is an iPCR assembly.')
#process the primer design work here
#get first 60 nucleotides from the sequence
sequence = row[3]
fw_primer = sequence[1:61]
print('Sequence of forward primer:')
print(fw_primer)
last_sixty = sequence[-60:]
## print(last_sixty)
re_primer = Seq(last_sixty).reverse_complement()
print('Sequence of reverse primer:')
print(re_primer)
#ending code: add 1 to counter and construct number
counter += 1
construct_number += 1
## if int(row[0]) == construct_number:
## else:
## counter += 1
## construct_number += 1
## print(temp_list)
## for row in temp_list:
## print(temp_list)
## print(temp_list[-1])
# fw_primer = temp_list[counter - 1].
(我知道代码可能看起来像菜鸟 - 除了介绍性的Java之外,我从未做过任何编程类。)
这段代码的问题在于,如果我有“构建”(又称质粒),我试图通过“Gibson”程序集构建它,它将处理第一个n-1质粒,但不是最后一个。 然而,我也想不出更好的方法来编写这段代码,但我可以看到,对于我正在尝试实现的工作流程,知道如何处理列表中的“n”事物,但每个“事物” “行数可变,对我来说非常方便。
我非常感谢任何人的帮助! 非常感谢!
这段代码的问题在于,如果我有“构建”(又称质粒),我试图通过“Gibson”程序集构建它,它将处理第一个n-1质粒,但不是最后一个。
这实际上是一个普遍问题,最简单的方法是在循环后添加一个检查,如下所示:
for row in construct_list:
do all your existing code
if we have a current Gibson list:
repeat the code to process it.
当然你不想重复自己...所以你将这项工作转移到一个函数中,你可以在两个地方调用它。
但是,我可能会使用groupby
不同的方式编写。 我知道乍一看这可能看起来“过于先进”,但值得一试,看看你是否能理解它,因为它让事情变得简单得多。
def get_strategy(row):
return row[0]
for group in itertools.groupby(construct_list, key=get_strategy):
现在,您将每个构造作为单独的列表,因此您根本不需要temp_list
。 例如,第一组将是:
[[1, 'Gibson', 'P(OmpC)-cI::P(cI)-LacZ controller'],
[1, 'Gibson', 'P(OmpC)-cI::P(cI)-LacZ controller'],
[1, 'Gibson', 'P(OmpC)-cI::P(cI)-LacZ controller']]
接下来将是:
[[2, 'iPCR', 'P(cpcG2)-K1F controller with K1F pos. feedback']]
并且最终不会有一个剩下的小组担心。
所以:
for group in itertools.groupby(construct_list, key=get_strategy):
construct_strategy = get_strategy(group[0])
if construct_strategy == "Gibson":
# your existing code, using group instead of temp_list,
# and no need to maintain temp_list at all
elif construct_strategy == 'iPCR":
# your existing code, using group[0] instead of row
一旦你克服了抽象障碍,以这种方式思考这个问题就简单多了。
事实上,一旦你开始直观地掌握迭代器,你就会开始发现itertools
(及其文档页面上的食谱,第三方库more_itertools
,以及你自己编写的类似代码)将很多复杂的问题转化为非常简单的。 “我如何跟踪行列表中当前匹配行组?”的答案。 是“保留一个临时列表,并记住每次更改组时再检查它,然后再检查剩余时间”,但对等效问题“我如何将行迭代转换为行组迭代?”的答案。 是“在groupby
包装迭代器”。
您还可能希望在assert
或其他检查中添加all(row[1] == construct_strategy for row in group[1:])
,即len(group) == 1
在iPCR
情况下,没有意外第三种策略等等,所以当你不可避免地遇到错误时,会更容易判断它是坏数据还是坏代码。
同时,不是使用csv.reader
,跳过第一行,并通过无意义的数字引用列,使用DictReader
可能更好:
with open('constructs-to-make.csv', 'rU') as constructs:
primer_list = []
def get_strategy(row):
return row["Strategy"]
for group in itertools.groupby(csv.DictReader(constructs), key=get_strategy):
# same as before, but with
# ... row["Construct"] instead of row[0]
# ... row["Strategy"] instead of row[1]
# ... row["Name"] instead of row[2]
只是python的一些常规编码帮助。 如果您还没有阅读PEP8,请执行此操作。
为了保持清晰的代码,将变量分配给记录/行中引用的字段会很有帮助。
我会为所引用的任何字段添加类似的内容:
construct_idx = 0
另外,我建议使用字符串格式,它更干净。
所以:
print('Current construct number is: #{} on row {}, which is a Gibson assembly'.format(row[construct_idx], counter))
代替:
print('Current construct number is: #' + row[0] + ' on row ' + str(counter) + ', which is a Gibson assembly')
如果你正在创建一个csv阅读器对象,使它的变量名称“* _list”可能会错过领先。 将其称为“* _reader”更直观。
construct_reader = csv.reader(constructs, delimiter=',')
代替:
construct_list = csv.reader(constructs, delimiter=',')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.