迭代在namedtuple和dicts上定义对的缓慢

时间:2017-01-10 21:36:57

标签: python collections defaultdict namedtuple

此代码在示例数据上快速运行,但是当迭代大文件时,它似乎运行缓慢,可能是因为嵌套的for循环。有没有其他原因为什么迭代defaultdict中的项目很慢?

import itertools

sample_genes1={"0002":["GENE1", "GENE2", "GENE3", "GENE4"],
               "0003":["GENE1", "GENE2", "GENE3", "GENE6"],
               "0202":["GENE4", "GENE2", "GENE1", "GENE7"]}

def get_common_gene_pairs(genelist):
    genedict={}
    for k,v in sample_genes1.items():
        listofpairs=[]
        for i in itertools.combinations(v,2):
            listofpairs.append(i)
            genedict[k]=listofpairs
    return genedict

from collections import namedtuple,defaultdict
def get_gene_pair_pids(genelist):
    i=defaultdict(list)
    d=get_common_gene_pairs(sample_genes1)
    Pub_genes=namedtuple("pair", ["gene1", "gene2"])
    for p_id,genepairs in d.iteritems():
        for p in genepairs:
            thispair=Pub_genes(p[0], p[1])
            if thispair in i.keys():
                i[thispair].append(p_id)
            else:
                i[thispair]=[p_id,]
    return i

if __name__=="__main__":
    get_gene_pair_pids(sample_genes1)

2 个答案:

答案 0 :(得分:2)

一个大问题:这一行:

if thispair in i.keys():

没有利用字典搜索,它是线性搜索。删除keys()调用,让字典快速查找:

if thispair in i:

但由于i是默认字典,当密钥不存在时会创建list,只需替换:

if thispair in i.keys():
    i[thispair].append(p_id)  # i is defaultdict: even if thispair isn't in the dict, it will create a list and append p_id.
else:
    i[thispair]=[p_id,]

通过这个简单的陈述:

i[thispair].append(p_id)

(它更快,因为只有一个散布p_id

总结一下:

  • 不要thispair in i.keys():它很慢,在python 2或3中,defaultdict或不是
  • 您已定义了defaultdict,但您的代码只假设为dict,但效果较慢。

注意:如果没有defaultdict,您可以刚刚删除.keys()或使用简单dict完成此操作:

i.setdefault(thispair,list)
i[thispair].append(p_id)

(此处默认项目取决于密钥)

除了:

def get_common_gene_pairs(genelist):
    genedict={}
    for k,v in sample_genes1.items():  # should be genelist, not the global variable, you're not using the genelist parameter at all

您在代码中根本没有使用sample_genes1的

答案 1 :(得分:1)

添加到Jean's answer,您可以使用 dict comprehension 优化您的get_common_gene_pairs功能:

def get_common_gene_pairs(genelist):
    return {k : list(itertools.combinations(v,2)) for k,v in genelist.items()}
list comprhension 计数器部分相比,

list.append()要花费更多时间。此外,您不必迭代itertools.combinations(v,2)以将其转换为列表。将其类型转换为list即可。

以下是我在回复Comparing list comprehensions and explicit loops时对列表理解list.append()进行的比较,以防您有兴趣看一下。