Math over list values of a dictionary with unlimited items

Question:

How do I loop through all keys list values one by one until I reach the end of the last list’s array value? All lists are the same length for each key.
I mean:

 my_dict1 = {'c1': [10, 11, 12], 'c2': [100, 110, 120], 'c3': [200, 210, 220]}
 my_dict2 = {'c1': 3, 'c2': 1, 'c3': 2}

The result I need to get is:

result = 0.5 * ([10 * 3 + 100 * 1 + 200 * 2] + [11 * 3 + 110 * 1 + 210 * 2] + [12 * 3 + 120 * 1 + 220 * 2])

I checked Multiplying the values of dictionaries with different keys and How to Multiply list elements in dictionary but they did not come in handy here.

The following just worked when two dictionary have the similar keys.

dict1 = {2: [10, 11, 12], 2: [100, 110, 120]}
dict2 = {2: [100, 110, 120], 2: [100, 110, 120]}
result = {i :[x*y for x, y in zip(dict1[i], dict2[i])] for i in dict1.keys()}
print(result)

Result:

{2: [10000, 12100, 14400]}

Should I work by the NumPy or Pandas to handle it? In my real job there is a dictionary or a data frame with unknown number of keys.

Asked By: user19396094

||

Answers:

One way just using zip:

arr = []
for k, v in my_dict1.items():
    c = my_dict2[k]
    arr.append([i * c for i in v])
    
out = [sum(a)/2 for a in zip(*arr)]

Or using pandas:

out = pd.DataFrame(my_dict1).mul(my_dict2).sum(axis=1).mul(0.5)

Output:

[265.0, 281.5, 298.0]
Answered By: Chris

If you just want to do the math…

my_dict1 = {'c1': [10, 11, 12], 'c2': [100, 110, 120], 'c3': [200, 210, 220]}
my_dict2 = {'c1': 3, 'c2': 1, 'c3': 2}

result=0
for i in my_dict1:
    for j in range(len(my_dict1[i])):
        result+=my_dict1[i][j]*my_dict2[i]
result/=2
print(result)
Answered By: kimhyunju

You must use the key from my_dict1 to find the multiplier in my dict2. From there on, you can just zip the lists and sum their items. It can be a plain Python inliner:

[sum(i)/2 for i in zip(*([i * my_dict2[k] for i in v] 
                         for k, v in my_dict1.items()))]

Above gives as expected:

[265.0, 281.5, 298.0]

You could also build 2 numpy arrays for the same operation:

arr1 = np.array(list(my_dict1.values()))
arr2 = np.array([my_dict2[k] for k in my_dict1])

Then:

np.sum(np.transpose(arr1) * arr2, axis=1)/2

gives as expected

array([265. , 281.5, 298. ])
Answered By: Serge Ballesta

It seems here using the Dataframe, Numpy and just python this question can be solved.
As Ballesta have replied based on Python:

[sum(i)/2 for i in zip(*([i * my_dict2[k] for i in v] 
                     for k, v in my_dict1.items()))]

Using Ballesta answer and Numpy:

arr1 = np.array(list(my_dict1.values()))
arr2 = np.array([my_dict2[k] for k in my_dict1])     
np.sum(np.transpose(arr1) * arr2, axis=1)/2

Or using pandas as Chris has answerd:

 out = pd.DataFrame(my_dict1).mul(my_dict2).sum(axis=1).mul(0.5)

A simpler way using the DataFrame could be:

import pandas as pd

df = pd.DataFrame({'c1': [10, 11, 12], 'c2': [100, 110, 120]})
df = df.reset_index()  # make sure indexes pair with number of rows

for index, row in df.iterrows():
    print((row['c1'] + row['c2'] )/ 2) 
Answered By: user19396094