1

私は生物工学の博士課程の学生で、研究の一部を自動化するために Python プログラミングを独学で学ぼうとしていますが、より大きなリスト内のサブリストを処理する際に問題が発生したようです。解決する。

基本的に、私がやろうとしていることの目標は、さまざまな DNA アセンブリ方法を使用して構築しているプラ​​スミド シーケンスのリストを含む CSV ファイルを処理し、必要なプライマー シーケンスを吐き出す小さなスクリプトを作成することです。プラスミドを構築するために注文します。

私が扱っているシナリオは次のとおりです。

プラスミドを構築したい場合、そのプラスミドの全配列を Excel スプレッドシートに入力する必要があります。「Gibson」と「iPCR」と呼ばれる 2 つの DNA アセンブリ方法のいずれかを選択する必要があります。各「iPCR」アセンブリには、リスト内の 1 行しか必要ありません。そのため、構築しようとしているプラ​​スミドの完全な配列を 1 つのセルに入れるだけでよいので、それらの連中を処理する方法は既に知っています。一方、「ギブソン」アセンブリでは、完全な DNA シーケンスを小さなチャンクに分割する必要があるため、1 つのプラスミドを完全に記述するために、Excel スプレッドシート内で 2 ~ 5 行が必要になる場合があります。

したがって、スプレッドシートは次のようになります。

構築.....戦略...名前

1.....ギブソン.....P(OmpC)-cI::P(cI)-LacZ コントローラ
1.....ギブソン.....P(OmpC)-cI::P(cI )-LacZ コントローラー
1.....Gibson.....P(OmpC)-cI::P(cI)-LacZ コントローラー
2.....iPCR.......P(cpcG2)- K1F 位置の K1F コントローラ。フィードバック
3.....ギブソン.....プロモーター位置がスワップされた P(cpcG2)-K1F コントローラー
3.....ギブソン.....プロモーター位置がスワップされた P(cpcG2)-K1F コントローラー
4.. ...iPCR.......P(cpcG2)-より強力な K1F RBS ライブラリを備えた K1F コントローラ

この長さのリストは十分に代表的だと思います。

私が直面している問題は、リストを実行してギブソンを処理できるようにしたいのですが、コードを思いどおりに動作させることができないようです。これまでに書いたコードは次のとおりです。

#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 個の「コンストラクト」(別名プラスミド) がある場合、最初の n-1 個のプラスミドは処理されますが、最後のプラスミドは処理されないことです。ただし、このコードを記述するためのより良い方法は考えられませんが、実装しようとしているワークフローについては、リスト内の「n」個のものを処理する方法を知っていることがわかりますが、それぞれの「もの」可変数の行の " は、私にとって本当に便利です。

ここで誰かの助けに本当に感謝します! どうもありがとう!

4

2 に答える 2

3

このコードの問題は、「Gibson」アセンブリによって構築しようとしている n 個の「コンストラクト」(別名プラスミド) がある場合、最初の 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です。

また、その場合、予期しない 3 番目の戦略などがないことassertなどのチェックを追加することもできます。これにより、必然的にエラーが発生した場合に、それが悪いデータであったかどうかを簡単に判断できます。または悪いコード。all(row[1] == construct_strategy for row in group[1:])len(group) == 1iPCR

csv.reader一方、 a を使用して最初の行をスキップし、意味のない数字で列を参照する代わりに、 aを使用する方がよい場合があり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]
于 2012-12-28T01:29:52.067 に答える
1

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=',')
于 2012-12-28T01:31:04.327 に答える