Using counter with nested dictionaries in python

I have a list of dicts in python, for example:

[
  {
    "25-34": {
      "Clicks": 10
    },
    "45-54": {
      "Clicks": 2
    },

  },
  {
    "25-34": {
      "Clicks": 20
    },
    "45-54": {
      "Clicks": 10
    },

  }   
]

how can i get the sum of the keys in each announcer of the list so i have:

{
    "25-34": {
        "Clicks": 30
    },
    "45-54": {
        "Clicks": 12
    },

}

I tried to use Counter(), but it works easily when the internal list is dictsflat, but with nested dicts, as mentioned above, gives this error:

    /usr/lib/python2.7/collections.pyc in update(self, iterable, **kwds)
        524                     self_get = self.get
        525                     for elem, count in iterable.iteritems():
    --> 526                         self[elem] = self_get(elem, 0) + count
        527                 else:
        528                     super(Counter, self).update(iterable) # fast path when counter is empty

TypeError: unsupported operand type(s) for +: 'dict' and 'dict'

How can I achieve the summation as described above.

NOTE : I added clicksfor sample only. nested voice recorders can have any keys, another example to make it more clear:

[
  {
    "25-34": {
      "Clicks": 10,
      "Visits": 1
    },
    "45-54": {
      "Clicks": 2,
      "Visits": 2
    },

  },
  {
    "25-34": {
      "Clicks": 20,
      "Visits": 3
    },
    "45-54": {
      "Clicks": 10,
      "Visits": 4
    },

  }   
]

output:

{
    "25-34": {
      "Clicks": 30,
      "Visits": 4
    },
    "45-54": {
      "Clicks": 12,
      "Visits": 6
    },

  }  
+4
source share
4 answers

From your edit, it sounds like you're just trying to summarize the values ​​of all the sub-icons with the parent dict:

In [9]: counts = Counter()

In [10]: for dd in data:
    ...:     for k,v in dd.items():
    ...:         counts[k] += sum(v.values())
    ...:

In [11]: counts
Out[11]: Counter({'25-34': 30, '45-54': 12})

, .

, , , defaultdict Counter factory:

In [17]: from collections import Counter, defaultdict

In [18]: counts = defaultdict(Counter)

In [19]: for dd in data:
    ...:     for k, d in dd.items():
    ...:         counts[k].update(d)
    ...:

In [20]: counts
Out[20]:
defaultdict(collections.Counter,
            {'25-34': Counter({'Clicks': 30, 'Visits': 4}),
             '45-54': Counter({'Clicks': 12, 'Visits': 6})})
+4

defaultdict int ( 0):

from collections import defaultdict
counter = defaultdict(int)

for current_dict in data:
    for key, value in current_dict.items():
        counter[key] += sum(value.values())

, .

+1

My options without a list comprehension:

def my_dict_sum(data):
"""
>>> test_data = [{"25-34": {"Clicks": 10, "Visits": 1}, "45-54": {"Clicks": 2, "Visits": 2}, },{"25-34": {"Clicks": 20, "Visits": 3}, "45-54": {"Clicks": 10, "Visits": 4}, }]
>>> my_dict_sum(test_data)
{'45-54': {'Clicks': 12, 'Visits': 6}, '25-34': {'Clicks': 30, 'Visits': 4}}
"""
result_key = data[0]
for x in data[1:]:
    for y in x:
        if y in result_key:
            for z in x[y]:
                if z in result_key[y]:
                    result_key[y][z] = result_key[y][z] + x[y][z]
return result_key
+1
source

For your first questions, here is a single line. It is not very pretty, but it uses Counter:

sum((Counter({k:v['Clicks'] for k,v in d.items()}) for d in data), Counter())

As an example:

data = [
  {
    "25-34": {
      "Clicks": 10
    },
    "45-54": {
      "Clicks": 2
    },

  },
  {
    "25-34": {
      "Clicks": 20
    },
    "45-54": {
      "Clicks": 10
    },

  }   
]

from collections import Counter

c = sum((Counter({k:v['Clicks'] for k,v in d.items()}) for d in data), Counter())
print(c)

It outputs:

Counter({'25-34': 30, '45-54': 12})
0
source

Source: https://habr.com/ru/post/1685722/


All Articles