列表比较两个文件之间的慢代码

时间:2017-05-20 16:37:02

标签: python

例如我有两个文件:

文件1:

id chrom start     end       strand
g1  11  98566330    98566433    -
g2  11  98566295    98566433    -
g3  11  98566581    98566836    -

file2的

id chrom   start   end      strand  gene_id            gene_name somecol1...somecol10
g1  11  98566330    98566433    -   ENSMUSG00000017210  Med24
g2  11  98566295    98566433    -   ENSMUSG00000017210  Med24
g3  11  98566581    98566836    -   ENSMUSG00000017210  Med24

期望的输出

id chrom start     end       strand gene_id gene_namesomecol1...somecol10
g1 11  98566330    98566433    -   ENSMUSG00000017210 Med24
g2 11  98566295    98566433    -   ENSMUSG00000017210 Med24
g3 11  98566581    98566836    -   ENSMUSG00000017210 Med24

我基本上想要做的是从两个文件中获取匹配id列,如果匹配,则在新文件中打印/写入file1和file2中的一些列(我当前的代码)

with open('~/outfile.txt', 'w') as w:
     for id1 in c1: #c1 is list where i append each line from file1
         for id2 in d1: #d2 is list where i append each line from file2
             if id1[0] in id2[0]: #is this condition faster (condition1)
         #   if id1[0] == id2[0]:#or this condition is faster (condition2)
                out = ('\t'.join(id2[0:6]),id1[1],id1[2],id2[9],id2[10])
                w.write('\t'.join(out) + '\n')

问题是这个代码按条件2工作,但它很慢可能是因为我试图匹配列表c1和d1之间的每一行id1[0] == id2[0],也因为file2有~500000行。

目前我只能提出两个我想要学习的条件,可能会使代码更快

是否有更好的逻辑可以提高速度。

编辑:

我需要匹配文件col0(id)和file2 col(id),如果是真,那么切片col0:6中的元素,来自file1的col [1,2]和来自file2的col9,10

期望的输出

id(file2) chrom(file2) start(file2)     end(file2)       strand(file2) gene_id(file2) gene_name(file2)somecol1(file1)...somecol10(file1)
g1 11  98566330    98566433    -   ENSMUSG00000017210 Med24
g2 11  98566295    98566433    -   ENSMUSG00000017210 Med24
g3 11  98566581    98566836    -   ENSMUSG00000017210 Med24

2 个答案:

答案 0 :(得分:1)

如果我理解正确,只有当id字段位于第一个文件中时,才希望保留第二个文件中的行。

我会一直使用csv模块,这更清晰。

首先,我将构建一组id字段,用于从文件1内容快速查找(每行只有5个字段)

然后我会读取第二个文件,并且仅当行id包含在集合中时才将行写入第三个文件。您将受益于set查找的速度:

import csv

with open("file1.txt") as file1:
    cr = csv.reader(file1,delimiter="\t")
    next(cr)  # skip title
    subset = {row[0] for row in cr} # build lookup set in a set comprehension for ids

with open("file2.txt") as file2, open("result.txt","w",newline="") as file3:  # python 2: open("result.txt","wb")
    cr = csv.reader(file2,delimiter="\t")
    cw = csv.writer(file3,delimiter="\t")
    cw.writerow(next(cr))  # write title
    cw.writerows(row for row in cr if row[0] in subset)

答案 1 :(得分:1)

您需要知道花费时间以了解如何最好地解决问题。猜测它将会读取和写入文件,其他一切都将达到......几乎没有。

如果您可以专注于问题领域,优化是很好的 - 这样其他所有内容都可以保持清晰可读的Python。因此,我首先要分析您的代码。 cProfile is a good place to start您的调查,可能还需要创建一些功能来划分您的工作,以便您可以看到花时间。

我最近做过edX ITMO竞争性编程课程,速度非常重要。 Python I / O是一个关键障碍,因此读取和写入都得到了优化。尽可能使用重要块进行写入,因此您可能需要在写入之前聚合数据。 Python的memory mapped reads被用来加快阅读速度。为了举例说明使用mmap的相对容易程度,顶部注释掉的代码执行下面未注释的readlines的mmap等价物:

    # with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as mm:
    #     end = mm.size()
    #     while mm.tell() < end:
    #         for l in mm.readline().split():
    #             print(';'.join(l.decode('ascii').split(',')))
    #  with open("out1", 'w') as o:
    with open(filename, 'r') as f:
        for l in f.readlines():
            #  ll.append('.'.join(l.split(',')))
            #  o.writelines(l[13:])
            #  print(l[13:], end='')
            print('.'.join(l.split(',')), end='')