简体   繁体   中英

How to sum up dict values based on combined key values?

My question is similar to this( Python sum on keys for List of Dictionaries ), but need to sum up the values based on two or more key-value elements. I have a list of dictionaries as following:

list_to_sum=
        [{'Name': 'A', 'City': 'W','amt':100},
         {'Name': 'B', 'City': 'A','amt':200},
         {'Name': 'A', 'City': 'W','amt':300},
         {'Name': 'C', 'City': 'X','amt':400},
         {'Name': 'C', 'City': 'X','amt':500},
         {'Name': 'A', 'City': 'W','amt':600}]
            

So based on a combination of Name and City key values, amt should be summed. Please let me know how to solve this.

Output: [{'Name': 'A', 'City': 'W','amt':900},
         {'Name': 'B', 'City': 'A','amt':200},
         {'Name': 'C', 'City': 'X','amt':900}]

You could create a collections.Counter .Then you can simply add the values as the appear using the tuple as (Name, City) as the key:

from collections import Counter

list_to_sum=[
    {'Name': 'A', 'City': 'W','amt':100},
    {'Name': 'B', 'City': 'A','amt':200},
    {'Name': 'A', 'City': 'W','amt':300},
    {'Name': 'C', 'City': 'X','amt':400},
    {'Name': 'C', 'City': 'X','amt':500},
    {'Name': 'A', 'City': 'W','amt':600}
]
    
totals = Counter()

for d in list_to_sum:
    totals[(d['Name'],d['City'])] += d['amt']

print(totals[('A','W')]) # 1000
print(totals[('B','A')]) # 200
print(totals[('C','X')]) # 900
      

This will produce a dictionary-like object Counter :

Counter({('A', 'W'): 1000, ('B', 'A'): 200, ('C', 'X'): 900})

With this you can convert the dict back to a list of dicts like:

sums_list = [{'Name':Name, 'City':City, 'amt':amt} for (Name, City), amt in totals.items()]

giving sums_list :

[{'Name': 'A', 'City': 'W', 'amt': 1000},
 {'Name': 'B', 'City': 'A', 'amt': 200},
 {'Name': 'C', 'City': 'X', 'amt': 900}]
list_to_sum = [{'Name': 'A', 'City': 'W', 'amt': 100},
               {'Name': 'B', 'City': 'A', 'amt': 200},
               {'Name': 'A', 'City': 'W', 'amt': 300},
               {'Name': 'C', 'City': 'X', 'amt': 400},
               {'Name': 'C', 'City': 'X', 'amt': 500},
               {'Name': 'A', 'City': 'W', 'amt': 600}]

sum_store = {}

for entry in list_to_sum:
    key = (entry['Name'], entry['City'])
    if key in sum_store:
        sum_store[key] += entry['amt']
    else:
        sum_store[key] = entry['amt']

print(sum_store)

output:

{('A', 'W'): 1000, ('B', 'A'): 200, ('C', 'X'): 900}

Besides the answers proposed by the others, it can be done in a pandas one-liner. It groups rows by name and city and calculates the sum over their amt feature.

import pandas as pd
list_to_sum=[
    {'Name': 'A', 'City': 'W','amt':100},
    {'Name': 'B', 'City': 'A','amt':200},
    {'Name': 'A', 'City': 'W','amt':300},
    {'Name': 'C', 'City': 'X','amt':400},
    {'Name': 'C', 'City': 'X','amt':500},
    {'Name': 'A', 'City': 'W','amt':600}
]

df = pd.DataFrame(list_to_sum)

t = df.groupby(['Name','City']).amt.sum()

print(t)

Output:
Name  City
A     W       400
B     A       200
C     X       900

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM