我有两个字典,每个字典用于计算两个列表中唯一字符串的实例数。他们看起来像这样,除了他们有数以千计的条目:
v[0] = d2_value/d1_value #fold change
v[1] = d1_value/d1_total #fraction of the total count (d1)
v[2] = d2_value/d2_total #fraction of the total count (d2)
我希望用d1和d2中出现的键填充新词典。我希望每个键的值都是一个列表v,其中包含以下内容:
d_new = {'pig':[4, 0.1, 0.4], 'cow':[0.5, 0.4, 0.2], 'sheep':'[0.2, 0.5, 0.1]}
所以最终的结果是:
def common_keys(d1, d2, d1_total, d2_total):
common = {}
for x, y in d1.iteritems():
for k, v in d2.iteritems():
d1_frac = y/d1_total
d2_frac = v/d2_total
fold_change = d2_frac/d1_frac
if x == k:
common[x] = [fold_change, d1_frac, d2_frac]
return commmon
我编写了以下代码,但是由于字典数量庞大,执行时间太长了:
common = {k:[???, (v/d1_total), (???/d2_total)] for k, v in d1.items() if k in d2.items()}
我觉得我应该用词典理解来提高速度,但我不知道如何从两个字典中收集价值......等等:
{{1}}
你能帮我写一下吗?非常感谢您的帮助。我最终总结了字典理解,但是当组合字典并将值修改为这样的列表时,事情会变得混乱。
答案 0 :(得分:3)
你不需要理解来提高速度。就个人而言,我会避免它,因为列表创建过于混乱,而且变得更难阅读。您需要的是更好的算法。具体来说,您可以通过执行密钥查找而不是迭代d2
来查找公共项目来更好地完成此操作:
def common_keys(d1, d2, d1_total, d2_total):
common = {}
for x, y in d1.iteritems():
try:
v = d2[x]
except KeyError:
continue
d1_frac = y/d1_total
d2_frac = v/d2_total
fold_change = d2_frac/d1_frac
common[x] = [fold_change, d1_frac, d2_frac]
return commmon
这样做可以摆脱内循环,节省大量时间。
答案 1 :(得分:3)
您可以在Python 3中使用密钥交集并执行:
d_new = {k: [d2[k]/d1[k], d1[k]/d1_total, d2[k]/d2_total]
for k in d1.keys() & d2.keys()}
在Python 2中使用set(d1).intersection(d2)
或d1.viewkeys() & d2.viewkeys()
。
另外,请注意Python 2中带有运算符/
的两个整数操作数的分层。
您可以使用d2[k]/float(d1[k]), ...
来避免分配。
答案 2 :(得分:1)
您可以使用条件字典理解。迭代d1
中的每个键,检查它是否在d2
d1_total = float(sum(d1.values()))
d2_total = float(sum(d2.values()))
>>> {k: [d2[k] / float(d1[k]), d1[k] / d1_total, d2[k] / d2_total]
for k in d1 if k in d2}
{'cow': [0.5, 0.4, 0.2], 'pig': [4.0, 0.1, 0.4], 'sheep': [0.2, 0.5, 0.1]}
<强>的时间设置强>
d1 = {n: 'a' for n in range(100000)}
d2 = {n: 'b' for n in range(50000, 150000)}
>>> %timeit [k for k in d1 if k in d2]
100 loops, best of 3: 10.1 ms per loop
>>> %timeit [k for k in d1.viewkeys() & d2.viewkeys()]
100 loops, best of 3: 10.5 ms per loop
时间应该相似。