EYakoumi
EYakoumi

Reputation: 429

Getting average of scores from 2 different dictionaries in python

I have a Python3 code that return 2 dictionaries (both have same indices) the first dictionary contains list of names, the second contains list scores.

for each of the indices the list might contain the name repeated and might contains different names as in the code below.

how can i get for each index of the dictionary, the average of each person in the list

I tried doing nested for loops on the indices to extract the list on each one

then after that i loop on each item in the name list, save indices for the name then reloop over the scores to get the average

names = {"0":['name1', 'name1', 'name2', 'name1'] , "1":['name1', 'name2', 'name2', 'name2', 'name2']}

scores = {"0":[0.5, 0.5, 1, 0.2], "1":[0.2, 0.8, 0.8, 0.9, 0.9]}

for ind in names:
    namelist = names[ind]
    scoreist = scores[ind]     #as ind in names is the same as in scores
.
.
.
    indices = list()
    counter = 0
    tempname = namelist[0]
    for name in names:
        if name == tempname:
            indices.append(counter)
        counter += 1

    total = 0
    for index in indicies:
    total += scorlist[index]

    average = total / scorelist

.
.
.

then i pop the indices of the list and re-iterate. I know there should be a faster, cleaner way to do that instead of nesting for loops in a while loop ...

EDIT:

The output should be something like

{"0": [['name1',0.3], ['name2', 0.25]], "1":[['name1', 0.05], ['name2', 0.68]]}

Upvotes: 1

Views: 1044

Answers (3)

unlut
unlut

Reputation: 3775

If cleaner code is an important consideration, I would suggest this solution. Although it may have worse running time complexity, but should not matter for small input sizes (maybe even efficient than naive Python loops?).

from collections import defaultdict

names = {"0":['name1', 'name1', 'name2', 'name1'] , "1":['name1', 'name2', 'name2', 'name2', 'name2']}
scores = {"0":[0.5, 0.5, 1, 0.2], "1":[0.2, 0.8, 0.8, 0.9, 0.9]}


result_dict = {}
for k,v in names.items():
    result_dict[k] = defaultdict(int)
    list_len = len(names[k])

    #  merge two lists of same key, and sort by name
    names_and_scores = sorted(zip(names[k], scores[k]), key = lambda x:x[0])

    #  sum tuples with same first element
    for key_tuple, val_tuple in names_and_scores:
        result_dict[k][key_tuple] += val_tuple / list_len

print(result_dict)

Upvotes: 1

Sociopath
Sociopath

Reputation: 13426

I think you need:

res = {}
for k,v in names.items():
    merged = [[i,j] for i,j in zip(names[k],scores[k])]
    # [['name1', 0.5], ['name1', 0.5], ['name2', 1], ['name1', 0.2]]                                                                        
    # [['name1', 0.2], ['name2', 0.8], ['name2', 0.8], ['name2', 0.9], ['name2', 0.9]]   
    s = []
    for i in set(names[k]):
        temp = sum([x[1] for x in merged if x[0]==i])/len(names[k])
        s.append([i, temp])

    res[k] = s

print(res)

Output:

{'1': [['name1', 0.04], ['name2', 0.6799999999999999]], 
 '0': [['name1', 0.3], ['name2', 0.25]]} 

Explanation

  • Create a 2D list merged with values from both dict
  • Find unique names and itereate over it to find average.

Upvotes: 1

Devesh Kumar Singh
Devesh Kumar Singh

Reputation: 20500

This gives you a dictionary with list of scores per name, and total number of elements for that list

numbers_dict = {}
for idx_1, name_list in names.items():
    values_dict = {}
    for idx_2,name in enumerate(name_list):
        if name in values_dict.keys():
            values_dict[name].append(scores[idx_1][idx_2])
        else:
            values_dict[name] = [scores[idx_1][idx_2]]
    values_dict['count'] = len(name_list)
    numbers_dict[idx_1] = values_dict

{'0': {'name1': [0.5, 0.5, 0.2], 'name2': [1], 'count': 4}, '1': {'name1': [0.2], 'name2': [0.8, 0.8, 0.9, 0.9], 'count': 5}}

Then you can use it to calculate your averages

avg_dict = {}
for idx, name_dict in numbers_dict.items():
    num_items = name_dict['count']
    dct = {}
    for name, numbers in name_dict.items():
        if name != 'count':
            dct[name] = sum(numbers)/num_items
    avg_dict[idx] = dct
print(avg_dict)
{'0': {'name1': 0.3, 'name2': 0.25}, '1': {'name1': 0.04, 'name2': 0.6799999999999999}}

Upvotes: 1

Related Questions