理解结合两个dicts和创建价值列表

时间:2017-08-03 21:02:33

标签: python merge dictionary-comprehension

我有两个字典,每个字典用于计算两个列表中唯一字符串的实例数。他们看起来像这样,除了他们有数以千计的条目:

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}}

你能帮我写一下吗?非常感谢您的帮助。我最终总结了字典理解,但是当组合字典并将值修改为这样的列表时,事情会变得混乱。

3 个答案:

答案 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

时间应该相似。