Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using counter with nested dictionaries in python

Tags:

python

i have a list of dicts in python like this:

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

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

  }   
]

how can i get the sum of keys in each dict of list such that i have:

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

}

I tried using Counter() but it works easily when the dicts inside list are flat but with the nested dicts like above it 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 i described above.

NOTE: i have added clicks just for sample. nested dicts can have any no of 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
    },

  }  
like image 871
anekix Avatar asked Sep 15 '17 06:09

anekix


People also ask

How do I get values from nested dictionaries?

Access Values using get() Another way to access value(s) in a nested dictionary ( employees ) is to use the dict. get() method. This method returns the value for a specified key. If the specified key does not exist, the get() method returns None (preventing a KeyError ).

Can you use count in dictionary Python?

method 3: Use len() function to count the number of keys in a dictionary. The len() function is used to find the length of objects. It returns the total number of items. In dictionaries, the items are stored in the form of key-value pairs which means that the total number of items and keys are equal.

How do you count items in a dictionary?

The number of distinct words (i.e. count of entries in the dictionary) can be found using the len() function.

How do you slice a nested dictionary in Python?

Slicing Nested Dictionary is not possible. We can shrink or grow nested dictionary as need. Like Dictionary, it also has key and value. Dictionary are accessed using key.


2 Answers

From your edit, it sounds like you are just trying to sum the values of all the sub-dicts, by 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})

Fundamentally, this is an unwieldy data-structure.

OK, given your last update, I think the easiest thing would be to go with a defaultdict with a 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})})
like image 161
juanpa.arrivillaga Avatar answered Oct 29 '22 04:10

juanpa.arrivillaga


My variation without list comprehensions:

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
like image 20
Eugene Dennis Avatar answered Oct 29 '22 05:10

Eugene Dennis