Python: Provide All Possible Sums Between Different Values of Variables
Question:
Maybe you will be able to help me to solve somewhat simple issue – I am trying to figure out how domain of possible outcomes look.
- Imagine I have multiple variables with different set of potential values:
A = [0.9, 0.7, 1, 0.5]
B = [0, 1]
C = [0.3, 0.6, 0.9]
D = [-1.8, 0]
I need a list of all possible sums of different values between these variables, for example:
- sum1: 0.9 + 0 + 0.3 + (-1.8) = -0.6
- sum2: 0.9 + 1 + 0.3 + (-1.8) = 0.4
- sum3: 0.9 + 0 + 0.6 + (-1.8) = -0.3
Best case scenario data should be in dataframe and if there are some true magicians scenario could be identified next to each output, for example
Scenario
Sum
A0.9_B0_C0.3_D-1.8
-0.6
A0.9_B1_C0.3_D-1.8
0.4
Hope you can help me to crack this! Thanks.
Answers:
This should work:
Note that you can re-arrange the order of the for-loops, if you want the output in a specific order.
import pandas as pd
A = [0.9, 0.7, 1, 0.5]
B = [0, 1]
C = [0.3, 0.6, 0.9]
D = [-1.8, 0]
scenario, my_sum = [], []
for a in A:
for b in B:
for c in C:
for d in D:
scenario.append(f"A{a}_B{b}_C{c}_D{d}")
my_sum.append(round(a+b+c+d, 2))
result = {"Scenario":scenario, "SUM":my_sum}
df = pd.DataFrame.from_dict(result)
print(df.head(5))
Output:
Showing only the first 5 results:
By re-arranging the for-loops:
for d in D:
for c in C:
for b in B:
for a in A:
scenario.append(f"A{a}_B{b}_C{c}_D{d}")
my_sum.append(round(a+b+c+d, 2))
You get the following result for the first 5 rows:
You can actually do this quite simply with the help of Numpy!
1) Initialise your lists as np.array:
import numpy as np
A = np.array([0.9, 0.7, 1, 0.5])
B = np.array([0, 1])
C = np.array([0.3, 0.6, 0.9])
D = np.array([-1.8, 0])
2) Create all possible combinations with np.meshgrid():
combinations = np.array(
np.meshgrid(A,B,C,D)).T.reshape(-1,4)
)
3) Calculate sums across all combinations (rows):
sums = combinations.sum(axis=1).reshape(-1,1)
4) Build Pandas dataframe:
import pandas as pd
arrays = ['A','B','C','D']
combinations_df = pd.DataFrame(np.hstack([combinations,sums]), columns=arrays+['sum'])
combinations_df.head()
Output:
By using numpy arrays instead of lists you’ll be able to make the code more readable and robust since all operations will be vectorised.
Now to get a "scenario" column scenario
we can use two simple apply’s:
combinations_df['scenario'] = combinations_df[arrays].apply(
lambda row: [f'{c[1]}{c[0]}' for c in list(zip(row,combinations_df.columns[:-1]))],
axis=1
).apply(lambda row: '_'.join(row))
combinations_df.head()
Output:
Maybe you will be able to help me to solve somewhat simple issue – I am trying to figure out how domain of possible outcomes look.
- Imagine I have multiple variables with different set of potential values:
A = [0.9, 0.7, 1, 0.5]
B = [0, 1]
C = [0.3, 0.6, 0.9]
D = [-1.8, 0]
I need a list of all possible sums of different values between these variables, for example:
- sum1: 0.9 + 0 + 0.3 + (-1.8) = -0.6
- sum2: 0.9 + 1 + 0.3 + (-1.8) = 0.4
- sum3: 0.9 + 0 + 0.6 + (-1.8) = -0.3
Best case scenario data should be in dataframe and if there are some true magicians scenario could be identified next to each output, for example
Scenario | Sum |
---|---|
A0.9_B0_C0.3_D-1.8 | -0.6 |
A0.9_B1_C0.3_D-1.8 | 0.4 |
Hope you can help me to crack this! Thanks.
This should work:
Note that you can re-arrange the order of the for-loops, if you want the output in a specific order.
import pandas as pd
A = [0.9, 0.7, 1, 0.5]
B = [0, 1]
C = [0.3, 0.6, 0.9]
D = [-1.8, 0]
scenario, my_sum = [], []
for a in A:
for b in B:
for c in C:
for d in D:
scenario.append(f"A{a}_B{b}_C{c}_D{d}")
my_sum.append(round(a+b+c+d, 2))
result = {"Scenario":scenario, "SUM":my_sum}
df = pd.DataFrame.from_dict(result)
print(df.head(5))
Output:
Showing only the first 5 results:
By re-arranging the for-loops:
for d in D:
for c in C:
for b in B:
for a in A:
scenario.append(f"A{a}_B{b}_C{c}_D{d}")
my_sum.append(round(a+b+c+d, 2))
You get the following result for the first 5 rows:
You can actually do this quite simply with the help of Numpy!
1) Initialise your lists as np.array:
import numpy as np
A = np.array([0.9, 0.7, 1, 0.5])
B = np.array([0, 1])
C = np.array([0.3, 0.6, 0.9])
D = np.array([-1.8, 0])
2) Create all possible combinations with np.meshgrid():
combinations = np.array(
np.meshgrid(A,B,C,D)).T.reshape(-1,4)
)
3) Calculate sums across all combinations (rows):
sums = combinations.sum(axis=1).reshape(-1,1)
4) Build Pandas dataframe:
import pandas as pd
arrays = ['A','B','C','D']
combinations_df = pd.DataFrame(np.hstack([combinations,sums]), columns=arrays+['sum'])
combinations_df.head()
Output:
By using numpy arrays instead of lists you’ll be able to make the code more readable and robust since all operations will be vectorised.
Now to get a "scenario" column scenario
we can use two simple apply’s:
combinations_df['scenario'] = combinations_df[arrays].apply(
lambda row: [f'{c[1]}{c[0]}' for c in list(zip(row,combinations_df.columns[:-1]))],
axis=1
).apply(lambda row: '_'.join(row))
combinations_df.head()
Output: