2015-03-29 2 views
2

Предположим, что у меня есть следующий список:Python список группировка и сумма

[{'name': 'Amy', 'count': 1}, {'name': 'Amy', 'count': 2}, {'name': 'Peter', 'count': 1}] 

Как я мог группа его и просуммировать количество, чтобы получить следующие из:

[{'name': 'Amy', 'count': 3}, {'name': 'Peter', 'count': 1}] 

Спасибо.

+0

возможно дубликат [ключевых значений словарных Group в питоне] (http://stackoverflow.com/questions/18180145/group-dictionary-key-values- in-python) – Aaron

ответ

4

Вы можете использовать collecions.Counter:

from collections import Counter 
l = [ 
    {'name': 'Amy', 'count': 1}, 
    {'name': 'Amy', 'count': 2}, 
    {'name': 'Peter', 'count': 1} 
] 
c = Counter() 
for v in l: 
    c[v['name']] += v['count'] 

Результат:

>>> c 
Counter({'Amy': 3, 'Peter': 1}) 
>>> [{'name': name, 'count': count} for name, count in c.items()] 
[{'count': 3, 'name': 'Amy'}, {'count': 1, 'name': 'Peter'}] 
+0

Спасибо, проблема решена сейчас. – Pang

1

Вы можете откинуть список с помощью defaultdict, как описано in the doc:

>>> l = [{'name': 'Amy', 'count': 1}, 
     {'name': 'Amy', 'count': 2}, 
     {'name': 'Peter', 'count': 1}] 

# Pivot operation 
>>> pivot = collections.defaultdict(list) 
>>> for item in l: 
...  pivot[item['name']].append(item['count']) 
... 
>>> pivot 
defaultdict(<class 'list'>, {'Peter': [1], 'Amy': [1, 2]}) 

После этого, вы просто должны восстановить желаемый результат, используя переменную ac Список omprehension:

>>> [{'name':k, 'count':sum(values)} for k, values in pivot.items()] 
[{'name': 'Peter', 'count': 1}, {'name': 'Amy', 'count': 3}] 

Я должен признать, что это не обязательно самый эффективный способ сделать, но, учитывая ваши структуры данных, я предполагаю, что операция поворота будет полезно в некоторых других случаях, не нужно подразумевающее суммированием вещей.

1
import itertools as it 
import operator as op 

l = [{'name': 'Amy', 'count': 1}, {'name': 'Amy', 'count': 2}, {'name': 'Peter', 'count': 1}] 

Получить список, отсортированный по ключу «имя» dict.

sl = sorted(l,key=op.itemgetter('name')) 

Pass отсортированный список gorupby с помощью ключа в качестве ключа «имя» в Словаре, который возвращает кортеж ключ и итератор элементов списка, сгруппированных по клавише «имя» в Словаре. F.E. ('Amy',<itertools._grouper object at 0xb5fdac2c>).

Итератор дает по одному элементу за итерацию все элементы списка, у которого «ами» есть значение для «имени» ключа dict.

Чтобы получить общее количество ключей «count», мы должны позвонить sum с новым списком всех полей «count», таких как sum(map(op.itemgetter('count'),g)).

Чтобы создать список Dict вызова dict с fitst элемента кортежа, возвращаемого groupby в качестве значения ключа «имя» и суммы, возвращаемой sum в качестве значения ключа «Count» для нового Dict.

[ dict(name=k,count=sum(map(op.itemgetter('count'),g))) 
    for k,g in it.groupby(sl, key=op.itemgetter('name'))] 
+2

Ваш ответ появился в очереди низкого качества. Пожалуйста, опишите * как * это отвечает на вопрос. Например, сложите одну строку кода и опишите каждую ее часть. Мы здесь не для того, чтобы работать для кого-то другого, но учили их делать свою работу. –

+0

обновил мое сообщение. нет перемотки? –

1

Я хотел бы предложить, что вы могли бы использовать defaultdict, как есть Sylvain Леру в его answer.

Однако, не надо собирать отсчеты в списке, вы можете подвести их, как вы идете с помощью defaultdict(int):

from collections import defaultdict 

l = [{'name': 'Amy', 'count': 1}, {'name': 'Amy', 'count': 2}, {'name': 'Peter', 'count': 1}] 

counts = defaultdict(int) 
for d in l: 
    counts[d['name']] += d['count'] 

counts = [{'name': k, 'count': v} for k,v in counts.items()] 

>>> print counts 
[{'count': 3, 'name': 'Amy'}, {'count': 1, 'name': 'Peter'}] 

Это должно быть более эффективным, чем построение списков и их суммирования.

itertools.groupby - это еще один вариант, но для этого требуется сортировка списка вверх по ключу name, что может быть менее эффективным для более длинных списков.

2

Вы можете альтернативно использовать панды функцию GroupBy:

df = pd.DataFrame([{'name': 'Amy', 'count': 1}, 
        {'name': 'Amy', 'count': 2}, 
        {'name': 'Peter', 'count': 1}]) 

df.groupby("name").sum() 

     count 
name   
Amy  3 
Peter  1 
Смежные вопросы