This is Edited New Answer With Runable Code
The following code will work even if number of rows are not equal. It will first take common rows on both dataframes and then finds the correct value for required column
import numpy as np
import pandas as pd
## creating dummy data to get runable code
## ---------------------------------------
n_rows = 20
sub_categories = np.random.choice(4, size=n_rows)
dic1 = {
"a": list(range(n_rows)),
"b": sub_categories,
"c": np.random.randn(n_rows)
}
dic2 = {
"a": range(n_rows),
"b": sub_categories,
"c": np.random.randn(n_rows)
}
df1 = pd.DataFrame(dic1)
df1.drop(index=list(np.random.choice(n_rows, 5, replace=False)), inplace=True)
df2 = pd.DataFrame(dic2)
df2.drop(index=list(np.random.choice(n_rows, 3, replace=False)), inplace=True)
## Main Answer
## ---------------------------------------------------------
## merge df1 and df2 then create new column c based which take min(abs(c_1, c_2))
result = df1.merge(df2, how="inner", on=["a","b"], suffixes=["_1", "_2"]).copy()
result["c"] = result["c_1"].where(np.abs(result["c_1"])<np.abs(result["c_2"]),
result["c_2"], axis=0)
display(result)
## finally reindex to remove extra columns
result = result.reindex(columns=["a","b","c"])
result
Old Answer
you can do something like below
series = df1["return"].where(np.abs(df1["return"])<np.abs(df2["return"]), df2["return"], axis=0)
series
it will return series whose value in a row is taken from df1 if absolute value of return is less than same row in df2 else it will take value from df2
then you can replace column of either df1 or df2 or their copy to get dataframe you want
df1["return"] = series