my main goal is to apply a function on a dataframe rows and add columns to that dataframe containing the results of each row. example :
run_id | bk1 | bk2 |
---|---|---|
2 | 1000 | 3 |
4 | 1890 | 3 |
to this result :
run_id | bk1 | bk2 | avg_inv | proc | shortage |
---|---|---|---|---|---|
2 | 1000 | 3 | 32,33 | 43 | 5 |
4 | 1890 | 3 | 45,22 | 4 | 17 |
Where avg_inv,proc
and shortage
are outputs of this function:
def order_up_to(demand_df,info_df,run,bk1,bk2):
...........
return proc,avg_inv,shortage
this function works well when i try it with one (run,bk1,bk2) it returns 3 integers but when i try to loop through all the rows and get the results in different lists i get this error :
avg=[]
proc=[]
shor=[]
for index,row in slc.iterrows():
avg.append(order_up_to(dmd,df,row["run_id"],row["bk1"],row["bk2"])[0])
proc.append(order_up_to(dmd,df,row["run_id"],row["bk1"],row["bk2"])[1])
shor.append(order_up_to(dmd,df,row["run_id"],row["bk1"],row["bk2"])[2])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [126], in <cell line: 4>()
3 shor=[]
4 for index,row in slc.iterrows():
----> 5 avg.append(order_up_to(dmd,df,row["run_id"],row["bk1"],row["bk2"])[0])
6 proc.append(order_up_to(dmd,df,row["run_id"],row["bk1"],row["bk2"])[1])
7 shor.append(order_up_to(dmd,df,row["run_id"],row["bk1"],row["bk2"])[2])
Input In [99], in ou2(demand_df, info_df, run, bk1, bk2)
12 purchase_qty=[0]*len(demand)
14 ######policy logic
---> 15 ending_inv_lvl[0]=initial_inv-demand[0]
16 if ending_inv_lvl[0]<=safety_stock :
17 purchase_qty[0]=order_qty-ending_inv_lvl[0]
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'
CodePudding user response:
applying the function to the dataframe columns instead of iterating through the rows makes it much easier:
def order_up_to(run_id, bk1, bk2):
# your function logic here
return avg_inv, proc, shortage
df = pd.DataFrame({'run_id': [2,4], 'bk1': [1000, 1890], 'bk2': [3, 3]})
[df["avg_inv"], df["proc"], df["shortage"]] = order_up_to(df.run_id, df.bk1, df.bk2)
CodePudding user response:
Rather than looping through the DataFrame
, you could use the apply
function and then split the result into separate columns -
d = dict(zip(['run_id', 'bk1', 'bk2'], [[2, 4], [1000, 1890], [3, 3]]))
df = pd.DataFrame(d)
def tuple_returning_func(row):
return 2*row['run_id'], 3*row['bk1'], 4*row['bk2']
df[list('abc')] = df.apply(tuple_returning_func, axis=1).apply(pd.Series)
output
run_id bk1 bk2 a b c
0 2 1000 3 4 3000 12
1 4 1890 3 8 5670 12