在Python中按键快速合并字典列表的方法
假设我有一堆字典。
a = {'x': 1.0, 'y': 0.5, 'z': 0.25 }
b = {'w': 0.5, 'x': 0.2 }
这里面只有两个字典,但我想讨论的是任意数量的字典。
我想知道,最快的办法是什么,来计算每个键的平均值。这些字典的内容比较稀疏,所以很多键在不同的字典里可能并不存在。
我想要的结果是一个新的字典,里面包含所有的键和每个键的平均值。值总是浮点数,我愿意使用ctypes。如果我现在的方法比较慢,可能是因为我在用defaultdict,这样即使某些值不存在,我也会初始化它们。如果这是导致慢的原因,我愿意重新考虑我的方法,只是想确保我没有忽略什么明显的东西。
编辑:我觉得我之前说得不太清楚,结果应该是,如果某个值不存在,就当作0.0,所以上面的例子结果应该是:
{'w':0.25,'x':0.6,'y':0.25,'z':0.125}
所以除法是用唯一键的总数来计算的。
我主要想知道有没有什么巧妙的方法,可以一步到位地对整个字典进行除法,或者一步到位地进行加法。简单来说,就是非常快速的向量加法和除法。我简单看了一下numpy数组,但它们似乎不适用于字典,如果我把字典转换成列表,就得把缺失的值显式设置为0,这样就失去了稀疏性。
6 个回答
1
>>> def avg(items):
... return sum(items) / len(items)
...
>>> hashes = [a, b]
>>> dict([(k, avg([h.get(k) or 0 for h in hashes])) for k in set(sum((h.keys() for h in hashes), []))])
{'y': 0.25, 'x': 0.59999999999999998, 'z': 0.125, 'w': 0.25}
解释:
所有哈希表中的键的集合,不重复。
set(sum((h.keys() for h in hashes), []))
对于上面集合中的每个键,计算它们的平均值。如果某个哈希表中没有这个键,就用0来代替。
(k, avg([h.get(k) or 0 for h in hashes]))
2
通过性能分析可能会证明,这并不是最快的方式,但...
import collections
a = {'x': 1.0, 'y': 0.5, 'z': 0.25 }
b = {'w': 0.5, 'x': 0.2 }
dicts = [a,b]
totals = collections.defaultdict(list)
avg = {}
for D in dicts:
for key,value in D.iteritems():
totals[key].append(value)
for key,values in totals.iteritems():
avg[key] = sum(values) / len(values)
我在这里猜测,让Python使用内置的 sum()
和 len()
函数,可能会在你看到新值时提高计算平均值的速度,不过我也可能错了。
2
这个方法可以用:
import collections
data= [
{'x': 1.0, 'y': 0.5, 'z': 0.25 },
{'w': 0.5, 'x': 0.2 }
]
tally = collections.defaultdict(lambda: (0.0, 0))
for d in data:
for k,v in d.items():
sum, count = tally[k]
tally[k] = (sum+v, count+1)
results = {}
for k, v in tally.items():
t = tally[k]
results[k] = t[0]/t[1]
print results
我不知道这个方法是否比你的快,因为你没有分享你的代码。
{'y': 0.5, 'x': 0.59999999999999998, 'z': 0.25, 'w': 0.5}
我尝试在计算时只记录总和和数量,这样就不需要再存储所有的值,最后再计算平均值。通常,在Python程序中,速度慢的原因是内存分配器的问题,减少内存的使用可以大大提高速度。