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.
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]
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)
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. ])
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)
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.
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]
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)
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. ])
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)