0

次の形式の大きな遺伝子ファイルを読み込んでいます

>GeneID
ACTCTCTCTATATATATATAT\n
GCTCTGCTTCTAGAGAGAGTG\n
TCTATTTGTTTATATATCTTT\n
>GeneID
GCTCTGCTTCTAGAAATTCCC\n
ACTCTGTATATATTTTCAAAA\n
GCTCTGCTTCTAGAGAGAGTG\n

各遺伝子は > で始まり、次に一意の ID です。その遺伝子のヌクレオチドの列が続きます。残念ながら、このファイルはシーケンスの各行の間に改行があるように生成されています。

各シーケンスを 1 つの連続した文字列として読み取る必要があります。そのため、次の方法を使用しています(以下を参照)。

for line in filer:
    if line.startswith(">"):

        # Find Sequences
        seq_seg = next(filer)
        seq = ""

        # Concatenate lines until find next gene
        while not (seq_seg.startswith(">")):
            seq += seq_seg.strip()  # Get rid of '\n'
            seq_seg = next(filer)

while ループが失敗する条件で next が呼び出されたときに、ファイル ポインターが次の遺伝子 ID を指しているため、スクリプトがファイル内の遺伝子の半分しか取得していないことがわかりました。ループが実行されると、次のファイルに移動します。

ファイルポインタを前の行に巻き戻す方法はありますか? for ループはそれを新しい遺伝子としてキャッチしますか?

同様の質問を見たことがありますが、ファイルを読んでいる特定の方法に対処するものはありません。

  for line in file:
        #do stuff
4

4 に答える 4

3

行をスキップする代わりにジェネレーターを使用します (これは大幅に簡略化できることがわかります)。

def parse_file(file):
    id = ''
    gene = ''

    for line in file:
        if line.startswith('>'):
            if gene:
                yield id, gene

            id = line[1:]
            gene = ''
        else:
            gene += line.strip()
    else:
        yield id, gene # Final gene

これで、ほんの数行のコードで全体を安全に繰り返すことができます。

with open('file.txt', 'r') as handle:
    for gene_id, nucleotides in parse_file(handle):
        print gene_id, nucleotides

pyfastaもあります。

または、より一般的な関数itertools:

def grouper(line):
    return line.startswith('>') and line[1:]

def itersplit(it, pred):
    groups = (list(group) for key, group in itertools.groupby(it, pred))
    yield from zip(groups, groups)

def parse(file):
    for key, group in itersplit(file, grouper):
        yield key[0], ''.join(group)
于 2013-07-16T21:04:55.863 に答える
1

ファイルポインタを前の行に巻き戻す方法はありますか? for ループはそれを新しい遺伝子としてキャッチしますか?

Python 3 では、いいえ。ファイルの反復と、ファイル ポインターに対する明示的な操作を混在させることはできません。

Python 2 では、たぶん。しかし、これは偶然にしか機能しないため、3.0 で禁止されました。また、すべての場合に適切に機能することが保証されているわけではありません。だから、あなたはそれをすべきではありません。

それを行うためのより良い方法は、 iteratorを巻き戻す方法を尋ねることです。答えはitertoolsです。を使用して先をのぞくことができますtee。イテレータを に再バインドできますchain([pushed_back_value], iterator)。等々。

しかし、他の人が指摘しているように、これを行うにはさらに良い方法があります。ここで先をのぞき見したり、後ろを探したりする必要はありません。物事をグループ化するだけで済みます。これも同様に実行できますitertoolsが、この場合、Blender が示すように、明示的に実行するだけで十分です。

于 2013-07-16T21:10:29.690 に答える
1

reandを使用する別の方法を次に示しますmmap

import mmap, re

with open(your_file) as fin:
    mm = mmap.mmap(fin.fileno(), 0, access=mmap.ACCESS_READ)
    for match in re.finditer('>([^\n]+)([^>]*)', mm, flags=re.DOTALL):
        print match.group(1), match.group(2).replace('\n', '')

#GeneID1 ACTCTCTCTATATATATATATGCTCTGCTTCTAGAGAGAGTGTCTATTTGTTTATATATCTTT
#GeneID2 GCTCTGCTTCTAGAAATTCCCACTCTGTATATATTTTCAAAAGCTCTGCTTCTAGAGAGAGTG

このようにすると、ファイル全体を文字列として扱うことができますが、オンデマンドでファイルの一部を提供する OS を利用して正規表現を完成させることができます。それが使用finditerするため、メモリ内に結果セットを構築していません。

于 2013-07-16T21:47:21.890 に答える
0

たとえば、fasta ファイルを読み取るためのはるかに簡単な方法があります。

entries = []
for line in filer:
    if line.startswith('>'):
        entries.append((line.rstrip()[1:], []))
    else:
        entries[-1][1].append(line.rstrip())

これにより、タプルのリストが表示されます。最初の要素はシーケンス ID で、2 番目の要素はシーケンスのリストです。

この後、シーケンスを結合するのは簡単です:

entries = [(x, "".join(y)) for x,y in entries]
于 2013-07-16T21:02:04.420 に答える