0

I have a dictionary with a list as value.

I want to have an average of this list. How do I compute that?

dict1 = {
    'Monty Python and the Holy Grail': [[9, 10, 9.5, 8.5, 3, 7.5, 8]],
    "Monty Python's Life of Brian": [[10, 10, 0, 9, 1, 8, 7.5, 8, 6, 9]],
    "Monty Python's Meaning of Life": [[7, 6, 5]],
    'And Now For Something Completely Different': [[6, 5, 6, 6]]
}

I have tried

dict2 = {}
for key in dict1:
    dict2[key] = sum(dict1[key])

but it says: "TypeError: unsupported operand type(s) for +: 'int' and 'list'"

pault
  • 32,557
  • 9
  • 66
  • 110
Christina
  • 53
  • 1
  • 1
  • 6

5 Answers5

4

As noted in other posts, the first issue is that your dictionary keys are lists of lists, and not simple lists. The second issue is that you were calling sum, without then dividing by the number of elements, which would not give you an average.

If you are willing to use numpy, try this:

import numpy as np
dict_of_means = {k:np.mean(v) for k,v in dict1.items()}

>>> dict_of_means
{'Monty Python and the Holy Grail': 7.9285714285714288, "Monty Python's Life of Brian": 6.8499999999999996, "Monty Python's Meaning of Life": 6.0, 'And Now For Something Completely Different': 5.75}

Or, without using numpy or any external packages, you can do it manually by first flattening your lists of lists in the keys, and going through the same type of dict comprehension, but getting the sum of your flattened list and then dividing by the number of elements in that flattened list:

dict_of_means = {k: sum([i for x in v for i in x])/len([i for x in v for i in x]) 
                      for k, v in dict1.items()}

Note that [i for x in v for i in x] takes a list of lists v and flattens it to a simple list.

FYI, the dictionary comprehension syntax is more or less equivalent to this for loop:

dict_of_means = {}
for k,v in dict1.items():
    dict_of_means[k] = sum([i for x in v for i in x])/len([i for x in v for i in x])

There is an in-depth description of dictionary comprehensions in the question I linked above.

sacuL
  • 42,057
  • 8
  • 58
  • 83
3

If you don't want to use external libraries and you want to keep that structure:

dict2 = {}
for key in dict1:
    dict2[key] = sum(dict1[key][0])/len(dict1[key][0])
Gonzalo Donoso
  • 557
  • 1
  • 4
  • 16
2

The problem is that your values are not 1D lists, they're 2D lists. If you simply remove the extra brackets, your solution should work.

Also don't forget to divide the sum of the list by the length of the list (and if you're using python 2, to import the new division).

Arya
  • 1,017
  • 12
  • 27
2

You can do that simply by using itertools.chain and a helper function to compute average.

Here is the helper function to compute average

def average(iterable):
    sum = 0.0
    count = 0
    for v in iterable:
        sum += v
        count += 1

    if count > 0:
        return sum / count

If you want to average for each key, you can simply do that using dictionary comprehension and helper function we wrote above:

from itertools import chain
averages = {k: average(chain.from_iterable(v)) for k, v in dict1.items()}

Or If you want to get average across all the keys:

from itertools import chain
average(chain.from_iterable(chain.from_iterable(dict1.values())))
Adnan Umer
  • 3,409
  • 2
  • 14
  • 35
1

Your lists are nested, all being lists of a single item, which is itself a list of the actual numbers. Here I extract these lists using val[0], val being the outer lists:

for key, val in dict1.copy().items():
    the_list = val[0]
    dict1[key] = sum(the_list)/len(the_list)

This replaces all these nested lists with the average you are after. Also, you should never mutate anything while looping over it. Therefore, a copy of the dict is used above.

Alternatively you could make use of the fancier dictionary comprehension:

dict2 = {key: sum(the_list)/len(the_list) for key, (the_list,) in dict1.items()}

Note the clever but subtle way the inner list is extracted here.

jmd_dk
  • 8,399
  • 4
  • 48
  • 72