为定义的对迭代 namedtuple 和 dicts 时速度缓慢
Slowness on iterating over namedtuple and dicts for defined pairs
这段代码 运行 在样本数据上很快,但是当遍历一个大文件时,它似乎 运行 很慢,这可能是因为嵌套的 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)
一个大问题:这一行:
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, or 3, defaultdict
or not
- 您已经定义了一个
defaultdict
,但是您的代码只是假定了一个 dict
,它可以工作但速度较慢。
注意:如果没有 defaultdict
,您可以删除 .keys()
或使用简单的 dict
:
i.setdefault(thispair,list)
i[thispair].append(p_id)
(这里默认项取决于key)
旁白:
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 的 值。
添加到 ,您的 get_common_gene_pairs
函数可以通过使用 dict comprehension 优化为:
def get_common_gene_pairs(genelist):
return {k : list(itertools.combinations(v,2)) for k,v in genelist.items()}
list.append() 比 list comprhension 对应部分要耗费更多时间。此外,您不必遍历 itertools.combinations(v,2)
即可将其转换为列表。将其类型转换为 list
即可。
这是我在 list comprehension 和 list.append()
之间的比较,以回答 ,如果您有兴趣可以看看。
这段代码 运行 在样本数据上很快,但是当遍历一个大文件时,它似乎 运行 很慢,这可能是因为嵌套的 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)
一个大问题:这一行:
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, or 3,defaultdict
or not - 您已经定义了一个
defaultdict
,但是您的代码只是假定了一个dict
,它可以工作但速度较慢。
注意:如果没有 defaultdict
,您可以删除 .keys()
或使用简单的 dict
:
i.setdefault(thispair,list)
i[thispair].append(p_id)
(这里默认项取决于key)
旁白:
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 的 值。
添加到 get_common_gene_pairs
函数可以通过使用 dict comprehension 优化为:
def get_common_gene_pairs(genelist):
return {k : list(itertools.combinations(v,2)) for k,v in genelist.items()}
list.append() 比 list comprhension 对应部分要耗费更多时间。此外,您不必遍历 itertools.combinations(v,2)
即可将其转换为列表。将其类型转换为 list
即可。
这是我在 list comprehension 和 list.append()
之间的比较,以回答