How to sum elements in list of dictionaries if two key values are the same
Clash Royale CLAN TAG#URR8PPP
up vote
10
down vote
favorite
I have the following list of dictionaries:
dictionary =['Flow': 100, 'Location': 'USA', 'Name': 'A1',
'Flow': 90, 'Location': 'Europe', 'Name': 'B1',
'Flow': 20, 'Location': 'USA', 'Name': 'A1',
'Flow': 70, 'Location': 'Europe', 'Name': 'B1']
I want to create a new list of dictionaries, with summed Flow
values of all dictionaries where Location
and Name
are the same. My desired output would be:
new_dictionary =['Flow': 120, 'Location': 'USA', 'Name': 'A1',
'Flow': 160, 'Location': 'Europe', 'Name': 'B1',]
How can I achieve this?
python list dictionary
add a comment |Â
up vote
10
down vote
favorite
I have the following list of dictionaries:
dictionary =['Flow': 100, 'Location': 'USA', 'Name': 'A1',
'Flow': 90, 'Location': 'Europe', 'Name': 'B1',
'Flow': 20, 'Location': 'USA', 'Name': 'A1',
'Flow': 70, 'Location': 'Europe', 'Name': 'B1']
I want to create a new list of dictionaries, with summed Flow
values of all dictionaries where Location
and Name
are the same. My desired output would be:
new_dictionary =['Flow': 120, 'Location': 'USA', 'Name': 'A1',
'Flow': 160, 'Location': 'Europe', 'Name': 'B1',]
How can I achieve this?
python list dictionary
add a comment |Â
up vote
10
down vote
favorite
up vote
10
down vote
favorite
I have the following list of dictionaries:
dictionary =['Flow': 100, 'Location': 'USA', 'Name': 'A1',
'Flow': 90, 'Location': 'Europe', 'Name': 'B1',
'Flow': 20, 'Location': 'USA', 'Name': 'A1',
'Flow': 70, 'Location': 'Europe', 'Name': 'B1']
I want to create a new list of dictionaries, with summed Flow
values of all dictionaries where Location
and Name
are the same. My desired output would be:
new_dictionary =['Flow': 120, 'Location': 'USA', 'Name': 'A1',
'Flow': 160, 'Location': 'Europe', 'Name': 'B1',]
How can I achieve this?
python list dictionary
I have the following list of dictionaries:
dictionary =['Flow': 100, 'Location': 'USA', 'Name': 'A1',
'Flow': 90, 'Location': 'Europe', 'Name': 'B1',
'Flow': 20, 'Location': 'USA', 'Name': 'A1',
'Flow': 70, 'Location': 'Europe', 'Name': 'B1']
I want to create a new list of dictionaries, with summed Flow
values of all dictionaries where Location
and Name
are the same. My desired output would be:
new_dictionary =['Flow': 120, 'Location': 'USA', 'Name': 'A1',
'Flow': 160, 'Location': 'Europe', 'Name': 'B1',]
How can I achieve this?
python list dictionary
asked Aug 27 at 5:51
user3200392
3061314
3061314
add a comment |Â
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
13
down vote
This is possible, but non-trivial to implement in python. Might I suggest using pandas? This is simple with a groupby
, sum
, and to_dict
.
import pandas as pd
(pd.DataFrame(dictionary)
.groupby(['Location', 'Name'], as_index=False)
.Flow.sum()
.to_dict('r'))
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
To install, use pip install --user pandas
.
Otherwise, you can apply a pseudo-generic group operation using itertools.groupby
.
from itertools import groupby
from operator import itemgetter
grouper = ['Location', 'Name']
key = itemgetter(*grouper)
dictionary.sort(key=key)
[**dict(zip(grouper, k)), 'Flow': sum(map(itemgetter('Flow'), g))
for k, g in groupby(dictionary, key=key)]
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
1
I want to downvote the unreadable one-liner in bottom half of the answer, but the top half of the answer looks perfectly ok. What should I do? :( (P.S.: You can simplify**'Flow': sum(map(itemgetter('Flow'), g))
to'Flow': sum(map(itemgetter('Flow'), g))
)
– Aran-Fey
Aug 27 at 10:26
add a comment |Â
up vote
5
down vote
While I would also prefer using Pandas if possible, here is solution using plain python:
In [1]: import itertools
In [2]: dictionary =['Flow': 100, 'Location': 'USA', 'Name': 'A1',
...: 'Flow': 90, 'Location': 'Europe', 'Name': 'B1',
...: 'Flow': 20, 'Location': 'USA', 'Name': 'A1',
...: 'Flow': 70, 'Location': 'Europe', 'Name': 'B1']
...:
In [3]: import operator
In [4]: key = operator.itemgetter('Location', 'Name')
In [5]: ['Flow': sum(x['Flow'] for x in g),
...: 'Location': k[0],
...: 'Name': k[1]
...: for k, g in itertools.groupby(sorted(dictionary, key=key), key=key)]
...:
...:
Out[5]:
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
Another way is to use defaultdict, which gives you a slightly different representation (though you can convert it back to list of dicts if you want):
In [11]: import collections
In [12]: cnt = collections.defaultdict(int)
In [13]: for r in dictionary:
...: cnt[(r['Location'], r['Name'])] += r['Flow']
...:
In [14]: cnt
Out[14]: defaultdict(int, ('Europe', 'B1'): 160, ('USA', 'A1'): 120)
In [15]: ['Flow': x, 'Location': k[0], 'Name': k[1] for k, x in cnt.items()]
Out[15]:
['Flow': 120, 'Location': 'USA', 'Name': 'A1',
'Flow': 160, 'Location': 'Europe', 'Name': 'B1']
add a comment |Â
up vote
4
down vote
Not exactly the output you expect, but..
Using collections.Counter()
count = Counter()
for i in dictionary:
count[i['Location'], i['Name']] += i['Flow']
print count
Will give:
Counter( ('Europe', 'B1'): 160,
('USA', 'A1'): 120 )
I hope this will at least give you some idea.
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
13
down vote
This is possible, but non-trivial to implement in python. Might I suggest using pandas? This is simple with a groupby
, sum
, and to_dict
.
import pandas as pd
(pd.DataFrame(dictionary)
.groupby(['Location', 'Name'], as_index=False)
.Flow.sum()
.to_dict('r'))
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
To install, use pip install --user pandas
.
Otherwise, you can apply a pseudo-generic group operation using itertools.groupby
.
from itertools import groupby
from operator import itemgetter
grouper = ['Location', 'Name']
key = itemgetter(*grouper)
dictionary.sort(key=key)
[**dict(zip(grouper, k)), 'Flow': sum(map(itemgetter('Flow'), g))
for k, g in groupby(dictionary, key=key)]
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
1
I want to downvote the unreadable one-liner in bottom half of the answer, but the top half of the answer looks perfectly ok. What should I do? :( (P.S.: You can simplify**'Flow': sum(map(itemgetter('Flow'), g))
to'Flow': sum(map(itemgetter('Flow'), g))
)
– Aran-Fey
Aug 27 at 10:26
add a comment |Â
up vote
13
down vote
This is possible, but non-trivial to implement in python. Might I suggest using pandas? This is simple with a groupby
, sum
, and to_dict
.
import pandas as pd
(pd.DataFrame(dictionary)
.groupby(['Location', 'Name'], as_index=False)
.Flow.sum()
.to_dict('r'))
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
To install, use pip install --user pandas
.
Otherwise, you can apply a pseudo-generic group operation using itertools.groupby
.
from itertools import groupby
from operator import itemgetter
grouper = ['Location', 'Name']
key = itemgetter(*grouper)
dictionary.sort(key=key)
[**dict(zip(grouper, k)), 'Flow': sum(map(itemgetter('Flow'), g))
for k, g in groupby(dictionary, key=key)]
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
1
I want to downvote the unreadable one-liner in bottom half of the answer, but the top half of the answer looks perfectly ok. What should I do? :( (P.S.: You can simplify**'Flow': sum(map(itemgetter('Flow'), g))
to'Flow': sum(map(itemgetter('Flow'), g))
)
– Aran-Fey
Aug 27 at 10:26
add a comment |Â
up vote
13
down vote
up vote
13
down vote
This is possible, but non-trivial to implement in python. Might I suggest using pandas? This is simple with a groupby
, sum
, and to_dict
.
import pandas as pd
(pd.DataFrame(dictionary)
.groupby(['Location', 'Name'], as_index=False)
.Flow.sum()
.to_dict('r'))
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
To install, use pip install --user pandas
.
Otherwise, you can apply a pseudo-generic group operation using itertools.groupby
.
from itertools import groupby
from operator import itemgetter
grouper = ['Location', 'Name']
key = itemgetter(*grouper)
dictionary.sort(key=key)
[**dict(zip(grouper, k)), 'Flow': sum(map(itemgetter('Flow'), g))
for k, g in groupby(dictionary, key=key)]
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
This is possible, but non-trivial to implement in python. Might I suggest using pandas? This is simple with a groupby
, sum
, and to_dict
.
import pandas as pd
(pd.DataFrame(dictionary)
.groupby(['Location', 'Name'], as_index=False)
.Flow.sum()
.to_dict('r'))
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
To install, use pip install --user pandas
.
Otherwise, you can apply a pseudo-generic group operation using itertools.groupby
.
from itertools import groupby
from operator import itemgetter
grouper = ['Location', 'Name']
key = itemgetter(*grouper)
dictionary.sort(key=key)
[**dict(zip(grouper, k)), 'Flow': sum(map(itemgetter('Flow'), g))
for k, g in groupby(dictionary, key=key)]
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
edited Aug 27 at 15:32


Aran-Fey
20k52858
20k52858
answered Aug 27 at 5:58


coldspeed
103k1787155
103k1787155
1
I want to downvote the unreadable one-liner in bottom half of the answer, but the top half of the answer looks perfectly ok. What should I do? :( (P.S.: You can simplify**'Flow': sum(map(itemgetter('Flow'), g))
to'Flow': sum(map(itemgetter('Flow'), g))
)
– Aran-Fey
Aug 27 at 10:26
add a comment |Â
1
I want to downvote the unreadable one-liner in bottom half of the answer, but the top half of the answer looks perfectly ok. What should I do? :( (P.S.: You can simplify**'Flow': sum(map(itemgetter('Flow'), g))
to'Flow': sum(map(itemgetter('Flow'), g))
)
– Aran-Fey
Aug 27 at 10:26
1
1
I want to downvote the unreadable one-liner in bottom half of the answer, but the top half of the answer looks perfectly ok. What should I do? :( (P.S.: You can simplify
**'Flow': sum(map(itemgetter('Flow'), g))
to 'Flow': sum(map(itemgetter('Flow'), g))
)– Aran-Fey
Aug 27 at 10:26
I want to downvote the unreadable one-liner in bottom half of the answer, but the top half of the answer looks perfectly ok. What should I do? :( (P.S.: You can simplify
**'Flow': sum(map(itemgetter('Flow'), g))
to 'Flow': sum(map(itemgetter('Flow'), g))
)– Aran-Fey
Aug 27 at 10:26
add a comment |Â
up vote
5
down vote
While I would also prefer using Pandas if possible, here is solution using plain python:
In [1]: import itertools
In [2]: dictionary =['Flow': 100, 'Location': 'USA', 'Name': 'A1',
...: 'Flow': 90, 'Location': 'Europe', 'Name': 'B1',
...: 'Flow': 20, 'Location': 'USA', 'Name': 'A1',
...: 'Flow': 70, 'Location': 'Europe', 'Name': 'B1']
...:
In [3]: import operator
In [4]: key = operator.itemgetter('Location', 'Name')
In [5]: ['Flow': sum(x['Flow'] for x in g),
...: 'Location': k[0],
...: 'Name': k[1]
...: for k, g in itertools.groupby(sorted(dictionary, key=key), key=key)]
...:
...:
Out[5]:
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
Another way is to use defaultdict, which gives you a slightly different representation (though you can convert it back to list of dicts if you want):
In [11]: import collections
In [12]: cnt = collections.defaultdict(int)
In [13]: for r in dictionary:
...: cnt[(r['Location'], r['Name'])] += r['Flow']
...:
In [14]: cnt
Out[14]: defaultdict(int, ('Europe', 'B1'): 160, ('USA', 'A1'): 120)
In [15]: ['Flow': x, 'Location': k[0], 'Name': k[1] for k, x in cnt.items()]
Out[15]:
['Flow': 120, 'Location': 'USA', 'Name': 'A1',
'Flow': 160, 'Location': 'Europe', 'Name': 'B1']
add a comment |Â
up vote
5
down vote
While I would also prefer using Pandas if possible, here is solution using plain python:
In [1]: import itertools
In [2]: dictionary =['Flow': 100, 'Location': 'USA', 'Name': 'A1',
...: 'Flow': 90, 'Location': 'Europe', 'Name': 'B1',
...: 'Flow': 20, 'Location': 'USA', 'Name': 'A1',
...: 'Flow': 70, 'Location': 'Europe', 'Name': 'B1']
...:
In [3]: import operator
In [4]: key = operator.itemgetter('Location', 'Name')
In [5]: ['Flow': sum(x['Flow'] for x in g),
...: 'Location': k[0],
...: 'Name': k[1]
...: for k, g in itertools.groupby(sorted(dictionary, key=key), key=key)]
...:
...:
Out[5]:
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
Another way is to use defaultdict, which gives you a slightly different representation (though you can convert it back to list of dicts if you want):
In [11]: import collections
In [12]: cnt = collections.defaultdict(int)
In [13]: for r in dictionary:
...: cnt[(r['Location'], r['Name'])] += r['Flow']
...:
In [14]: cnt
Out[14]: defaultdict(int, ('Europe', 'B1'): 160, ('USA', 'A1'): 120)
In [15]: ['Flow': x, 'Location': k[0], 'Name': k[1] for k, x in cnt.items()]
Out[15]:
['Flow': 120, 'Location': 'USA', 'Name': 'A1',
'Flow': 160, 'Location': 'Europe', 'Name': 'B1']
add a comment |Â
up vote
5
down vote
up vote
5
down vote
While I would also prefer using Pandas if possible, here is solution using plain python:
In [1]: import itertools
In [2]: dictionary =['Flow': 100, 'Location': 'USA', 'Name': 'A1',
...: 'Flow': 90, 'Location': 'Europe', 'Name': 'B1',
...: 'Flow': 20, 'Location': 'USA', 'Name': 'A1',
...: 'Flow': 70, 'Location': 'Europe', 'Name': 'B1']
...:
In [3]: import operator
In [4]: key = operator.itemgetter('Location', 'Name')
In [5]: ['Flow': sum(x['Flow'] for x in g),
...: 'Location': k[0],
...: 'Name': k[1]
...: for k, g in itertools.groupby(sorted(dictionary, key=key), key=key)]
...:
...:
Out[5]:
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
Another way is to use defaultdict, which gives you a slightly different representation (though you can convert it back to list of dicts if you want):
In [11]: import collections
In [12]: cnt = collections.defaultdict(int)
In [13]: for r in dictionary:
...: cnt[(r['Location'], r['Name'])] += r['Flow']
...:
In [14]: cnt
Out[14]: defaultdict(int, ('Europe', 'B1'): 160, ('USA', 'A1'): 120)
In [15]: ['Flow': x, 'Location': k[0], 'Name': k[1] for k, x in cnt.items()]
Out[15]:
['Flow': 120, 'Location': 'USA', 'Name': 'A1',
'Flow': 160, 'Location': 'Europe', 'Name': 'B1']
While I would also prefer using Pandas if possible, here is solution using plain python:
In [1]: import itertools
In [2]: dictionary =['Flow': 100, 'Location': 'USA', 'Name': 'A1',
...: 'Flow': 90, 'Location': 'Europe', 'Name': 'B1',
...: 'Flow': 20, 'Location': 'USA', 'Name': 'A1',
...: 'Flow': 70, 'Location': 'Europe', 'Name': 'B1']
...:
In [3]: import operator
In [4]: key = operator.itemgetter('Location', 'Name')
In [5]: ['Flow': sum(x['Flow'] for x in g),
...: 'Location': k[0],
...: 'Name': k[1]
...: for k, g in itertools.groupby(sorted(dictionary, key=key), key=key)]
...:
...:
Out[5]:
['Flow': 160, 'Location': 'Europe', 'Name': 'B1',
'Flow': 120, 'Location': 'USA', 'Name': 'A1']
Another way is to use defaultdict, which gives you a slightly different representation (though you can convert it back to list of dicts if you want):
In [11]: import collections
In [12]: cnt = collections.defaultdict(int)
In [13]: for r in dictionary:
...: cnt[(r['Location'], r['Name'])] += r['Flow']
...:
In [14]: cnt
Out[14]: defaultdict(int, ('Europe', 'B1'): 160, ('USA', 'A1'): 120)
In [15]: ['Flow': x, 'Location': k[0], 'Name': k[1] for k, x in cnt.items()]
Out[15]:
['Flow': 120, 'Location': 'USA', 'Name': 'A1',
'Flow': 160, 'Location': 'Europe', 'Name': 'B1']
answered Aug 27 at 6:02
soon
19.6k44470
19.6k44470
add a comment |Â
add a comment |Â
up vote
4
down vote
Not exactly the output you expect, but..
Using collections.Counter()
count = Counter()
for i in dictionary:
count[i['Location'], i['Name']] += i['Flow']
print count
Will give:
Counter( ('Europe', 'B1'): 160,
('USA', 'A1'): 120 )
I hope this will at least give you some idea.
add a comment |Â
up vote
4
down vote
Not exactly the output you expect, but..
Using collections.Counter()
count = Counter()
for i in dictionary:
count[i['Location'], i['Name']] += i['Flow']
print count
Will give:
Counter( ('Europe', 'B1'): 160,
('USA', 'A1'): 120 )
I hope this will at least give you some idea.
add a comment |Â
up vote
4
down vote
up vote
4
down vote
Not exactly the output you expect, but..
Using collections.Counter()
count = Counter()
for i in dictionary:
count[i['Location'], i['Name']] += i['Flow']
print count
Will give:
Counter( ('Europe', 'B1'): 160,
('USA', 'A1'): 120 )
I hope this will at least give you some idea.
Not exactly the output you expect, but..
Using collections.Counter()
count = Counter()
for i in dictionary:
count[i['Location'], i['Name']] += i['Flow']
print count
Will give:
Counter( ('Europe', 'B1'): 160,
('USA', 'A1'): 120 )
I hope this will at least give you some idea.
answered Aug 27 at 7:22
Nimeshka Srimal
2,66722237
2,66722237
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52033242%2fhow-to-sum-elements-in-list-of-dictionaries-if-two-key-values-are-the-same%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password