Reputation: 429
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
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
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
merged
with values from both dict
Upvotes: 1
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