python操作文件,脚本中的逻辑错误?

时间:2016-02-11 13:47:04

标签: python loops coordinates file-manipulation

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

CHR-坐标覆盖

chr1    236968289   2
chr1    236968318   2
chr1    236968320   2
chr1    236968374   2
chr1    237005709   2
chr14   22086843    2
chr14   22086846    2
chr14   22086849    2
chr14   22086851    4
chr2    5078129 2
chr2    5341758 2
chr2    5342443 2

我想操纵它来获得:

chr-start-end-average coverage-distance

chr1  236968289  236968374 2    85    
chr14 22086843   22086851  2.5  8
chr2  5078129    5078129   2    0
chr2  5341758    5342443   2    685

我想要那样: 如果chr与之前的chr 不同,则坐标之间的差异大于1000:它会打印输出,如图所示。使用chr,起始坐标,结束坐标,平均覆盖范围以及开始和结束之间的距离。

为此,我编写了以下代码:

cov=open("coverage.txt")
oldchr="chr55"      #dummy starting data
oldcoordinate=1
sumcoverage=0
startcoordinate=0

try:
   while True:
    line=next(cov).split("\t",2)
    newchr=line[0]
    newcoordinate=int(line[1])       #read informations from file
    newcoverage=int(line[2].strip())

    if oldchr != newchr or newcoordinate - oldcoordinate > 1000:
        distance=oldcoordinate-startcoordinate
        averagecoverage=sumcoverage/distance
        merge=oldchr+'\t'+str(startcoordinate)+'\t'+str(oldcoordinate)+'\t'+str(averagecoverage)+'\t'+str(distance) 
        print merge
        startcoordinate=newcoordinate
        sumcoverage=0

    oldchr=newchr
    oldcoordinate=newcoordinate     #replace old with new chr and coordinates
    sumcoverage=sumcoverage+newcoverage


except(StopIteration):
    print ""

我无法理解为什么它不能正常工作。 我得到的错误是获得"平均覆盖率的划分"试图按0分割,所以在很多情况下,"距离" ( distance = oldcoordinate-startcoordinate )等于0。 这不应该发生,在输入文件中永远不会出现2行具有相同坐标的情况。我无法看到错误的位置。 我希望有人可以帮助我,提前谢谢你。

1 个答案:

答案 0 :(得分:0)

您可以使用Python的groupby功能根据chr列对您的条目进行分组。 csv库还可以更轻松地处理文件:

from itertools import groupby
import csv

def display_block(block):
    average_coverage = sum(x[2] for x in block) / float(len(block))
    print block[0][0], "\t", block[0][1], "\t", block[-1][1], "\t", average_coverage, "\t", block[-1][1] - block[0][1]


with open('coverage.txt', 'rb') as f_coverage:
    for chr, entries in groupby(csv.reader(f_coverage, delimiter='\t'), lambda x: x[0]):
        entries = [(e[0], int(e[1]) , int(e[2])) for e in entries]
        block = []
        ientries = iter(entries)
        block.append(next(ientries))

        for chr, coord, coverage in ientries:
            if coord - block[-1][1] > 1000:
                display_block(block)
                block = []
            block.append([chr, coord, coverage])

        if len(block):
            display_block(block)

这将显示以下输出:

chr1    236968289   236968374   2.0     85
chr1    237005709   237005709   2.0     0
chr14   22086843    22086851    2.5     8
chr2    5078129     5078129     2.0     0
chr2    5341758     5342443     2.0     685

for循环的每次迭代都会为您提供当前chr以及该chr的所有匹配行。该脚本遍历每一行并将coordcoverage转换为整数。然后它将列表作为迭代器。第一个匹配行存储在block中,然后迭代任何剩余的行。每次距离大于1000时,都会显示并重新启动块。然后还会显示最后的任何剩余条目。

使用Python 2.7.6进行测试