Python用字符串作为分隔符拆分

时间:2015-03-20 10:14:09

标签: python string-split file-writing

我有一个看起来像这样的文件:

AAACAACAGGGTACAAAGAGTCACGCTTATCCTGTTGATACT
TCTCAATGGGCAGTACATATCATCTCTNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNAAAACGTGTGCATGAACAAAAAA
CGTAGCAGATCGTGACTGGCTATTGTATTGTGTCAATTTCGCTTCGTCAC
TAAATCAACGGACATGTGTTGC

我需要将其拆分为“非N”序列,因此有两个单独的文件:

AAACAACAGGGTACAAAGAGTCACGCTTATCCTGTTGATACT
TCTCAATGGGCAGTACATATCATCTCT

AAAACGTGTGCATGAACAAAAAACGTAGCAGATCGTGACTGGC
TATTGTATTGTGTCAATTTCGCTTCGTCACTAAATCAACGGACA
TGTGTTGC

我现在拥有的是:

UMfile = open ("C:\Users\Manuel\Desktop\sequence.txt","r")
contignumber = 1
contigfile = open ("contig "+str(contignumber), "w")

DNA = UMfile.read()
DNAstring = str(DNA)

for s in DNAstring:
    DNAstring.split("NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN",1)
contigfile.write(DNAstring)

contigfile.close()
contignumber = contignumber+1
contigfile = open ("contig "+str(contignumber), "w")

问题是我意识到“Ns”之间存在一个换行符,这就是为什么它没有拆分我的文件,但我展示的“文件”只是一个更大的文件的一部分。因此,有时候“Ns”看起来像“NNNNNN \ n”,有时候会像“NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN

所以我的问题是:我怎么告诉python每1000xN分成不同的文件,知道每行中会有不同数量的N?

非常感谢你们,我真的没有信息学背景,而且我的python技能至多是基本的。

3 个答案:

答案 0 :(得分:1)

只需在'N'上拆分字符串,然后删除所有空字符串,或只包含换行符。像这样:

#!/usr/bin/env python

DNAstring = '''AAACAACAGGGTACAAAGAGTCACGCTTATCCTGTTGATACT
TCTCAATGGGCAGTACATATCATCTCTNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNAAAACGTGTGCATGAACAAAAAA
CGTAGCAGATCGTGACTGGCTATTGTATTGTGTCAATTTCGCTTCGTCAC
TAAATCAACGGACATGTGTTGC'''

sequences = [u for u in DNAstring.split('N') if u and u != '\n']

for i, seq in enumerate(sequences):
    print i
    print seq.replace('\n', '') + '\n'

<强>输出

0
AAACAACAGGGTACAAAGAGTCACGCTTATCCTGTTGATACTTCTCAATGGGCAGTACATATCATCTCT

1
AAAACGTGTGCATGAACAAAAAACGTAGCAGATCGTGACTGGCTATTGTATTGTGTCAATTTCGCTTCGTCACTAAATCAACGGACATGTGTTGC

上面的代码段也会使用.replace('\n', '')删除序列中的换行符。


以下是一些您可能会觉得有用的程序。

首先是行缓冲类。您使用文件名和行宽初始化它。然后,您可以为其提供随机长度字符串,它将自动将它们逐行保存到文本文件中,所有行(除了可能是最后一行)具有给定长度。您可以在其他程序中使用此类来使输出看起来整洁。

将此文件保存为linebuffer.py到Python路径中的某个位置;最简单的方法是将它保存在保存Python程序的任何地方,并在运行程序时将其保存为当前目录。

<强> linebuffer.py

#! /usr/bin/env python

''' Text output buffer 

    Write fixed width lines to a text file

    Written by PM 2Ring 2015.03.23
'''

class LineBuffer(object):
    ''' Text output buffer

        Write fixed width lines to file fname
    '''
    def __init__(self, fname, width):
        self.fh = open(fname, 'wt')
        self.width = width
        self.buff = []
        self.bufflen = 0

    def write(self, data):
        ''' Write a string to the buffer '''
        self.buff.append(data)
        self.bufflen += len(data)
        if self.bufflen >= self.width:
            self._save()

    def _save(self):
        ''' Write the buffer to the file '''
        buff = ''.join(self.buff)

        #Split buff into lines
        lines = []
        while len(buff) >= self.width:
            lines.append(buff[:self.width])
            buff = buff[self.width:]

        #Add an empty line so we get a trailing newline
        lines.append('')
        self.fh.write('\n'.join(lines))  

        self.buff = [buff]
        self.bufflen = len(buff)

    def close(self):
        ''' Flush the buffer & close the file '''
        if self.bufflen > 0:
            self.fh.write(''.join(self.buff) + '\n')
        self.fh.close()


def testLB():
    alpha = 'abcdefghijklmnopqrstuvwxyz'
    fname = 'linebuffer_test.txt'
    lb = LineBuffer(fname, 27)
    for _ in xrange(30):
        lb.write(alpha)
    lb.write(' bye.')
    lb.close()


if __name__ == '__main__':
    testLB()

这是一个程序,可以生成您在问题中描述的形式的随机DNA序列。它使用linebuffer.py来处理输出。我写了这个,所以我可以正确测试我的DNA序列分裂器。

<强> Random_DNA0.py

#! /usr/bin/env python

''' Make random DNA sequences

    Sequences consist of random subsequences of the letters 'ACGT'
    as well as short sequences of 'N', of random length up to 200.
    Exactly 1000 'N's separate sequence blocks. 
    All sequences may contain newlines chars 

    Takes approx 3 seconds per megabyte generated and saved 
    on a 2GHz CPU single core machine.

    Written by PM 2Ring 2015.03.23
'''

import sys
import random
from linebuffer import LineBuffer

#Set seed to None to seed randomizer from system time
random.seed(37)

#Output line width
linewidth = 120

#Subsequence base length ranges
minsub, maxsub = 15, 300

#Subsequences per sequence ranges
minseq, maxseq = 5, 50

#random 'N' sequence ranges
minn, maxn = 5, 200

#Probability that a random 'N' sequence occurs after a subsequence
randn = 0.2

#Sequence separator
nsepblock = 'N' * 1000

def main():
    #Get number of sequences from the command line
    numsequences = int(sys.argv[1]) if len(sys.argv) > 1 else 2
    outname = 'DNA_sequence.txt'

    lb = LineBuffer(outname, linewidth)
    for i in xrange(numsequences):
        #Write the 1000*'N' separator between sequences
        if i > 0:
            lb.write(nsepblock)

        for j in xrange(random.randint(minseq, maxseq)):
            #Possibly make a short run of 'N's in the sequence
            if j > 0 and random.random() < randn:
                lb.write(''.join('N' * random.randint(minn, maxn)))

            #Create a single subsequence
            r = xrange(random.randint(minsub, maxsub))
            lb.write(''.join([random.choice('ACGT') for _ in r]))
    lb.close()


if __name__ == '__main__':
    main()

最后,我们有一个程序可以分割您的随机DNA序列。再一次,它使用linebuffer.py来处理输出。

<强> DNA_Splitter0.py

#! /usr/bin/env python

''' Split DNA sequences and save to separate files

    Sequences consist of random subsequences of the letters 'ACGT'
    as well as short sequences of 'N', of random length up to 200.
    Exactly 1000 'N's separate sequence blocks. 
    All sequences may contain newlines chars 

    Written by PM 2Ring 2015.03.23
'''

import sys
from linebuffer import LineBuffer

#Output line width
linewidth = 120

#Sequence separator
nsepblock = 'N' * 1000

def main():
    iname = 'DNA_sequence.txt'
    outbase = 'contig'

    with open(iname, 'rt') as f:
        data = f.read()

    #Remove all newlines
    data = data.replace('\n', '')

    sequences = data.split(nsepblock)

    #Save each sequence to a series of files
    for i, seq in enumerate(sequences, 1):
        outname = '%s%05d' % (outbase, i)
        print outname

        #Write sequence data, with line breaks
        lb = LineBuffer(outname, linewidth)
        lb.write(seq)
        lb.close()


if __name__ == '__main__':
    main()

答案 1 :(得分:0)

您可以简单地用空格替换每个N和\ n,然后拆分。

result = DNAstring.replace("\n", " ").replace("N", " ").split()

这将返回一个字符串列表,以及&#39; ACGT&#39;序列也将与每个新行分开。

如果这不是你的目标,你想要保留&#39; ACGT&#39;而不是沿着它分开,你可以做到以下几点:

result = DNAstring.replace("N\n", " ").replace("N", " ").split()

如果它位于N序列的中间,则只会删除\ n。

要在1000 Ns之后准确分割字符串

# 1/ Get rid of line breaks in the N sequence
result = DNAstring.replace("N\n", "N")
# 2/ split every 1000 Ns
result = result.split(1000*"N")

答案 2 :(得分:0)

假设您可以一次阅读整个文件

s=DNAstring.replace("\n","")         # first remove the nasty linebreaks
l=[x for x in s.split("N") if x]     # split and drop empty lines

for x in l:                          # print in chunks
    while x:
        print x[:10]
        x=x[10:]
    print                            # extra linebreak between chunks