How to sum elements in list of dictionaries if two key values are the same

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
10
down vote

favorite
3












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?







share|improve this question
























    up vote
    10
    down vote

    favorite
    3












    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?







    share|improve this question






















      up vote
      10
      down vote

      favorite
      3









      up vote
      10
      down vote

      favorite
      3






      3





      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?







      share|improve this question












      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?









      share|improve this question











      share|improve this question




      share|improve this question










      asked Aug 27 at 5:51









      user3200392

      3061314




      3061314






















          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']





          share|improve this answer


















          • 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

















          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']





          share|improve this answer



























            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.






            share|improve this answer




















              Your Answer





              StackExchange.ifUsing("editor", function ()
              StackExchange.using("externalEditor", function ()
              StackExchange.using("snippets", function ()
              StackExchange.snippets.init();
              );
              );
              , "code-snippets");

              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "1"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              convertImagesToLinks: true,
              noModals: false,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );













               

              draft saved


              draft discarded


















              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






























              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']





              share|improve this answer


















              • 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














              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']





              share|improve this answer


















              • 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












              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']





              share|improve this answer














              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']






              share|improve this answer














              share|improve this answer



              share|improve this answer








              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












              • 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












              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']





              share|improve this answer
























                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']





                share|improve this answer






















                  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']





                  share|improve this answer












                  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']






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Aug 27 at 6:02









                  soon

                  19.6k44470




                  19.6k44470




















                      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.






                      share|improve this answer
























                        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.






                        share|improve this answer






















                          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.






                          share|improve this answer












                          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.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Aug 27 at 7:22









                          Nimeshka Srimal

                          2,66722237




                          2,66722237



























                               

                              draft saved


                              draft discarded















































                               


                              draft saved


                              draft discarded














                              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













































































                              Comments

                              Popular posts from this blog

                              What does second last employer means? [closed]

                              List of Gilmore Girls characters

                              Confectionery