【问题标题】:How to reduce/aggregate a list of dicts per multiple keys in Python?如何减少/聚合 Python 中每个键的字典列表?
【发布时间】:2014-06-18 21:50:11
【问题描述】:

我有一个这样的字典列表:

sales_per_store_per_day = [
   {'date':'2014-06-01', 'store':'a', 'product1':10, 'product2':3, 'product3':15},
   {'date':'2014-06-01', 'store':'b', 'product1':20, 'product2':4, 'product3':16},
   {'date':'2014-06-02', 'store':'a', 'product1':30, 'product2':5, 'product3':17},
   {'date':'2014-06-02', 'store':'b', 'product1':40, 'product2':6, 'product3':18},
]

我怎样才能减少这个列表,让每个商店都有一个产品总和,而忽略日期?上述输入的结果将是:

sales_per_store = [
   {'store':'a', 'product1':40, 'product2':8, 'product3':32},
   {'store':'b', 'product1':60, 'product2':10, 'product3':34}
]

【问题讨论】:

  • 你觉得怎么样?你试过什么,它到底有什么问题?为什么不将sales_per_store 制作成字典字典{store: {product: count, ...}, ...}

标签: python dictionary


【解决方案1】:

使用collections.defaultdict() 来跟踪每个商店的信息,使用collections.Counter() 来简化数字的求和:

from collections import defaultdict, Counter

by_store = defaultdict(Counter)

for info in sales_per_store_per_day:
    counts = Counter({k: v for k, v in info.items() if k not in ('store', 'date')})
    by_store[info['store']] += counts

sales_per_store = [dict(v, store=k) for k, v in by_store.items()]

counts 是由info 字典中的每个产品构建的Counter() 实例;我假设除了storedate 键之外的所有东西都是产品计数。它使用 dict 理解来生成删除了这两个键的副本。 by_store[info['store']] 查找给定存储的当前总计数(默认为新的空 Counter() 对象)。

最后一行会产生你想要的输出;带有 'store' 和每个产品计数的新字典,但您可能只想保留从 store 到 Counter 对象的字典映射。

演示:

>>> from collections import defaultdict, Counter
>>> sales_per_store_per_day = [
...    {'date':'2014-06-01', 'store':'a', 'product1':10, 'product2':3, 'product3':15},
...    {'date':'2014-06-01', 'store':'b', 'product1':20, 'product2':4, 'product3':16},
...    {'date':'2014-06-02', 'store':'a', 'product1':30, 'product2':5, 'product3':17},
...    {'date':'2014-06-02', 'store':'b', 'product1':40, 'product2':6, 'product3':18},
... ]
>>> by_store = defaultdict(Counter)
>>> for info in sales_per_store_per_day:
...     counts = Counter({k: v for k, v in info.items() if k not in ('store', 'date')})
...     by_store[info['store']] += counts
... 
>>> [dict(v, store=k) for k, v in by_store.items()]
[{'store': 'a', 'product3': 32, 'product2': 8, 'product1': 40}, {'store': 'b', 'product3': 34, 'product2': 10, 'product1': 60}]

【讨论】:

  • Martijn...这是一个优雅的解决方案。好的。是否可以编辑以包含一些关于for info in sales... 循环内两行实际发生的情况的basics 讨论? ...为了普通教育?
【解决方案2】:

没有collections 的版本 - 对初学者来说可能更易读。

sales_per_store_per_day = [
   {'date':'2014-06-01', 'store':'a', 'product1':10, 'product2':3, 'product3':15},
   {'date':'2014-06-01', 'store':'b', 'product1':20, 'product2':4, 'product3':16},
   {'date':'2014-06-02', 'store':'a', 'product1':30, 'product2':5, 'product3':17},
   {'date':'2014-06-02', 'store':'b', 'product1':40, 'product2':6, 'product3':18},
]

results = {}

for x in sales_per_store_per_day:

    # default value
    if x['store'] not in results:
        results[x['store']] = {'store': x['store'], 'product1':0, 'product2':0, 'product3':0}

    results[x['store']]['product1'] += x['product1']
    results[x['store']]['product2'] += x['product2']
    results[x['store']]['product3'] += x['product3']

print results

sales_per_store = results.values()

print sales_per_store

.

# results
{
  'a': {'product3': 32, 'product1': 40, 'store': 'a', 'product2': 8}, 
  'b': {'product3': 34, 'product1': 60, 'store': 'b', 'product2': 10}
}

# sales_per_store
[
  {'product3': 32, 'product1': 40, 'store': 'a', 'product2': 8}, 
  {'product3': 34, 'product1': 60, 'store': 'b', 'product2': 10}
]

【讨论】:

    猜你喜欢
    • 2021-03-03
    • 2014-05-16
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-07
    • 1970-01-01
    • 2020-05-07
    相关资源
    最近更新 更多