Skip to main content
 首页 » 编程设计

python之慢 python 代码似乎适合 itertools : how to optimize

2025年05月04日29tuyile006

我有这个:

entity_key = 'pid' 
data = [ { ... }, { ... } ] 
entities = list(set([ row[entity_key] for row in data ])) 
parsed = [] 
total_keys = ['a','b','c'] 
for entity_id in entities: 
    entity_rows = [ row for row in data if row[entity_key] == entity_id ] 
    totals = { key: sum(filter(None, [ row.get(key) for row in entity_rows ])) for key in total_keys } 
    totals[entity_key] = entity_id 
    parsed.append(totals) 
return parsed 

在我的场景中,data 大约有 30,000 个项目,它很大。

每一项都是一个dict,每个dict包含标识符pid,以及total_keys <中定义的每一项的数值< code> ,例如 { 'pid': 5011, 'a': 3, 'b': 20, 'c': 33 }

如您所见,代码为每个 pid 返回一个唯一行列表,并在 total_keys 列表中定义汇总列。可能有大约 800-1000 个唯一的 pid 值,所以 parsed 最终是大约 800-1000 个项目。

它很慢。我尝试使用 itertools.groupby 重写它,但它似乎不是最合适的。有什么我想念的魔法吗?

请您参考如下方法:

使用 pids 作为外键创建一个字典:

entity_key = 'pid' 
 
data = [ { 'pid': 5011, 'a': 3, 'b': 20, 'c': 33 },{ 'pid': 5012, 'a': 3, 'b': 20, 'c': 33 },  
{ 'pid': 5011, 'a': 3, 'b': 20, 'c': 33 },{ 'pid': 5012, 'a': 3, 'b': 20, 'c': 33 }] 
 
 
from collections import defaultdict 
 
totals = ["a", "b", "c"] 
 
dfd = defaultdict(lambda: {"a":0, "b", 0, "c": 0}) 
for d in data: 
    for k in d.keys() & totals: 
        dfd[d["pid"]][k] += d[k] 

输出将是所有 pid 的分组和任何 b 或 c 键值的总和:

defaultdict(<function <lambda> at 0x7f2cf93ed2f0>, 
 {5011: {'a': 6, 'c': 66, 'b': 40}, 5012: {'a': 6, 'c': 66, 'b': 40}}) 

对于 python2 你需要使用 uni = d.viewkeys() & totals

如果您的数据实际上是分组的,您可以一次生成一组:

from collections import defaultdict 
from itertools import groupby 
from operator import itemgetter 
 
def yield_d(data,k, keys): 
    for k,v in groupby(data, key=itemgetter(k)): 
        d = defaultdict(lambda: dict.fromkeys(keys, 0)) 
        for dct in v: 
            for _k in dct.keys() & keys: 
                d[k][_k] += dct[_k] 
        yield d