Currently, your method expects to receive scalar values but you pass Pandas Series (i.e., columns of data frames) into the method. Hence, the if logic needs to check every element of the Series (a structure of many same-type values) and not one value. Consequently, you receive the error of ambiguous truth value. Newcomers of Pandas often face this error coming from general purpose Python. Pandas/Numpy maintain a different object model than general Python.
To resolve, because you are essentially calculating new fields with conditional logic, consider binding all Series parameters into one data frame. Then, replace the general Python construct of if...elif...else for numpy.where that runs logic across higher dimensional objects such as arrays.
class feasible:
def __init__(self, old_difference, for_value, back_value, fall_back_value):
# HORIZONTAL MERGE (OUTER JOIN) ON INDEX
x_frame = (pd.concat([old_difference, for_value, back_value, fall_back_value], axis = 1)
.set_axis(['old_difference', 'for_value', 'back_value', 'fall_back_value'],
axis = 'columns', inplace = False)
)
# ASSIGN NEW CALCULATED COLUMNS
x_frame['diff'] = (x_frame['for_value'] - x_frame['back_value']).abs()
x_frame['for_diff'] = (x_frame['for_value'] - x_frame['fall_back_value']).abs()
x_frame['back_diff'] = (x_frame['back_value'] - x_frame['fall_back_value']).abs()
# ASSIGN FINAL SERIES BY NESTED CONDITIONAL LOGIC
self.value = np.where(x_frame['diff'] < x_frame['old_difference'],
(x_frame['for_value'] + x_frame['back_value'])/2,
np.where(x_frame['for_diff'] < x_frame['back_diff'],
x_frame['for_value'],
x_frame['back_value']
)
)
Now depending on the row size of all four data frames, different implementation of result must be handled. Specifically, pd.concat at axis = 1 by default runs on join='outer' so all rows are retained in the horizontal merge operation with NaN filled in for unmatched rows.
If filler_frame (the data frame you intend to add a column) is equal to all rows then a simple assignment is doable.
# IF filler_frame CONTAINS THE MOST ROWS (OR EQUIVALENT TO MOST) OF ALL FOUR DFs
feasible_x = feasible(diff_frame.x,for_frame.x,back_frame.x,filler_frame.x)
filler_frame['x_new'] = feasible_x.value
If not a left join for new column, x_new is required. Below will work across all cases including above.
# IF filler_frame DOES NOT CONTAIN MOST ROWS OF ALL FOUR DFs
feasible_x = feasible(diff_frame.x,for_frame.x,back_frame.x,filler_frame.x)
filler_frame = filler_frame.join(pd.Series(feasible_x.value).rename('x_new'), how = 'left')