对辅助数据帧进行迭代搜索以将值返回到主数据帧新列

Jor*_*ias 5 python function dataframe pandas

我有两个数据框 - df1 和 df2。我需要在 df2 上的 df1 中的特定列中搜索每个值并返回 2 个最接近的值。

data1 = np.array([(1, 150), (2, 250), (3, 350), (4, 590)])
df1 = pd.DataFrame(data1, columns=['n', 'day'])

df1
    n   day
0   1   150
1   2   250
2   3   350
3   4   590
Run Code Online (Sandbox Code Playgroud)
data2 = np.array([(120, 10.5), (180, 10.7), (350, 11.2), (620, 15.5)])
df2 = pd.DataFrame(data2, columns=['day', 'rate'])

df2
    day rate
0   120 10.5
1   180 10.7
2   350 11.2
3   620 15.5
Run Code Online (Sandbox Code Playgroud)

我设法使用此函数找到这些值:

#to find 2 nearest values
def find_rates(df, s, x, n=2):
    diff = (s - x).abs()
    return df.loc[diff.nsmallest(n).index].sort_index()
Run Code Online (Sandbox Code Playgroud)

示例:

find_rates(df2, df2.day, 150, n=2)

         day    rate
0   120.0   10.5
1   180.0   10.7

find_rates(df2, df2.day, 350, n=2)
     day    rate
1   180.0   10.7
2   350.0   11.2
Run Code Online (Sandbox Code Playgroud)

我期望的是在 df2 上迭代搜索 df1 中的每个“天”值,并将 2 个最接近的值存储在 df1 新列上:

data3 = np.array([(1, 150, 120, 180, 10.5, 10.7), (2, 250, 180, 350, 10.7, 11.2), (3, 350, 180, 350, 10.7, 11.2), (4, 590, 350, 620, 11.2, 15.5)])
want = pd.DataFrame(data3, columns=['n', 'day', 'day1', 'day2', 'rate1', 'rate2'])
want
     n  day     day1    day2    rate1   rate2
0   1.0 150.0   120.0   180.0   10.5    10.7
1   2.0 250.0   180.0   350.0   10.7    11.2
2   3.0 350.0   180.0   350.0   10.7    11.2
3   4.0 590.0   350.0   620.0   11.2    15.5
Run Code Online (Sandbox Code Playgroud)

有关如何做到这一点的任何线索?

Tim*_*ess 6

另一种可能的解决方案:

N = 2

day1 = df1["day"].to_numpy()[:, None]
day2 = df2["day"].to_numpy(); arr2 = df2.to_numpy()
idx = np.sort(np.argsort(np.abs(day2 - day1), axis=1)[:, :N])

days  = pd.DataFrame(arr2[:, 0][idx], columns=["day1",  "day2"])
rates = pd.DataFrame(arr2[:, 1][idx], columns=["rate1", "rate2"])

out = pd.concat([df1, days, rates], axis=1)
Run Code Online (Sandbox Code Playgroud)

输出 :

print(out)

   n  day   day1   day2  rate1  rate2
0  1  150 120.00 180.00  10.50  10.70
1  2  250 180.00 350.00  10.70  11.20
2  3  350 180.00 350.00  10.70  11.20
3  4  590 350.00 620.00  11.20  15.50
Run Code Online (Sandbox Code Playgroud)