我的数据由一系列类别组成,每个类别都有两个数量。例如,{'cat':'red', 'a':1, 'b':2}, {'cat':'red', 'a':3, 'b':3}, {'cat':'blue', 'a':1, 'b':3}
我希望按类别保持两个金额的总计。结果将是{'cat':'red', 'a':4, 'b':5}, {'cat':'blue', 'a':1, 'b':3}
是否有更多的pythonic方法:
totals = {}
for item in data:
if item['cat'] in totals:
totals[item['cat']]['a'] += item['a']
totals[item['cat']]['b'] += item['b']
else:
totals[item['cat']] = {'a':item['a'], 'b':item['b']}
答案 0 :(得分:2)
您的数据结构应该真正移动到字典,键入cat
值。使用collections.defaultdict()
和collections.Counter()
来跟踪这些值并简化求和:
from collections import defaultdict, Counter
totals = defaultdict(Counter)
for item in data:
cat = item.pop('cat')
totals[cat] += Counter(item)
演示:
>>> from collections import defaultdict, Counter
>>> data = {'cat':'red', 'a':1, 'b':2}, {'cat':'red', 'a':3, 'b':3}, {'cat':'blue', 'a':1, 'b':3}
>>> totals = defaultdict(Counter)
>>> for item in data:
... cat = item.pop('cat')
... totals[cat] += Counter(item)
...
>>> totals
defaultdict(<class 'collections.Counter'>, {'blue': Counter({'b': 3, 'a': 1}), 'red': Counter({'b': 5, 'a': 4})})
>>> totals['blue']
Counter({'b': 3, 'a': 1})
>>> totals['red']
Counter({'b': 5, 'a': 4})
如果您仍需要相同格式的字典序列,则可以将上述字典字典再次转换为“普通”字典:
output = []
for cat, counts in totals.iteritems():
item = {'cat': cat}
item.update(counts)
output.append(item)
导致:
>>> output
[{'a': 1, 'b': 3, 'cat': 'blue'}, {'a': 4, 'b': 5, 'cat': 'red'}]
答案 1 :(得分:1)
查看dict.setdefault和collections.counter。 使用setdefault的可能解决方案:
totals = {}
for item in data:
d = totals.setdefault(item['cat'], {'a':0, 'b':0})
d['a'] += item['a']
d['b'] += item['b']
结果为total = {'blue': {'a': 1, 'b': 3}, 'red': {'a': 4, 'b': 5}}
。请注意,这没有预期答案中的'cat'
条目。相反,颜色直接用作结果字典的键。
请参阅Martijn的答案,了解使用Counter
的示例。
答案 2 :(得分:0)
我会根据collections.Counter
和collections.defaultdict
类的组合将您的数据收集到临时复合数据结构中。这个数据结构的关键是猫的颜色,并且与每个颜色相关联将是Counter
来保存每个颜色猫的总数。将它设为defaultdict
意味着不必担心它是否第一次遇到颜色。
这将在创建时执行所需值的求和,并且很容易变成您想要的输出序列:
from collections import Counter, defaultdict
data = ({'cat':'red', 'a':1, 'b':2},
{'cat':'red', 'a':3, 'b':3},
{'cat':'blue', 'a':1, 'b':3})
cat_totals = defaultdict(Counter) # hybrid data structure
for entry in data:
cat_totals[entry['cat']].update({k:v for k,v in entry.iteritems()
if k != 'cat'})
results = tuple(dict([('cat', color)] + cat_totals[color].items())
for color in cat_totals)
print results # ({'a': 1, 'b': 3, 'cat': 'blue'}, {'a': 4, 'b': 5, 'cat': 'red'})