0

我有由一系列类别组成的数据,每个类别都有两个数量。例如,{'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']}
4

3 回答 3

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'}]
于 2013-09-07T08:28:46.657 回答
1

看看dict.setdefaultcollections.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'您预期答案中的条目。相反,颜色直接用作结果字典的键。

有关使用Counter.

于 2013-09-07T08:23:47.110 回答
0

我会将您的数据收集到基于collections.Countercollections.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'})
于 2013-09-07T12:34:53.963 回答