如何在Python中基于薪资相近性将两个DataFrame按ID映射?
实现方法
我们可以利用numpy的广播机制高效完成匹配,或者用apply方法实现更直观的逻辑,以下是两种可行方案:
方案一:高效广播法(适合大数据量)
通过数组广播计算差值,快速定位最接近的薪资记录:
import pandas as pd import numpy as np # 生成原始数据 data_set_1 = {'id': [1,2,3,4,5], 'Available_Salary': [10,20,30,40,50]} df_1 = pd.DataFrame(data_set_1) data_set_2 = {'id': [1,2,3,4,5,6,7,8,9,10], 'Expected_Salary': [9,49,18,19,29,41,4,57,42,3]} df_2 = pd.DataFrame(data_set_2) # 提取df_1的参考数据数组 salary_ref = df_1['Available_Salary'].to_numpy() id_ref = df_1['id'].to_numpy() # 广播计算每条Expected_Salary与所有参考薪资的绝对差 diff_matrix = np.abs(df_2['Expected_Salary'].to_numpy()[:, np.newaxis] - salary_ref) # 找到每行差值最小的索引(对应df_1的行位置) min_indices = np.argmin(diff_matrix, axis=1) # 映射对应薪资和id到df_2 df_2['Salary_from_df_1'] = salary_ref[min_indices] df_2['id_from_df_1'] = id_ref[min_indices] print(df_2)
代码说明
- 广播运算将df_2的薪资列转为列向量,与df_1的薪资行向量计算差值,生成
(10,5)的差值矩阵,每一行对应df_2一条记录与df_1所有薪资的差。 np.argmin按行取最小差值的索引,直接定位df_1中最匹配的行。- 通过索引从参考数组中提取对应值,完成新列赋值。
方案二:apply直观法(适合小数据集)
用apply逐行处理,逻辑更易懂:
import pandas as pd import numpy as np # 生成原始数据(同方案一) data_set_1 = {'id': [1,2,3,4,5], 'Available_Salary': [10,20,30,40,50]} df_1 = pd.DataFrame(data_set_1) data_set_2 = {'id': [1,2,3,4,5,6,7,8,9,10], 'Expected_Salary': [9,49,18,19,29,41,4,57,42,3]} df_2 = pd.DataFrame(data_set_2) def match_closest_salary(row): # 计算当前薪资与df_1所有薪资的绝对差,取差值最小的行 closest_record = df_1.loc[np.abs(df_1['Available_Salary'] - row['Expected_Salary']).idxmin()] return pd.Series([closest_record['Available_Salary'], closest_record['id']]) # 应用函数到df_2每一行,生成新列 df_2[['Salary_from_df_1', 'id_from_df_1']] = df_2.apply(match_closest_salary, axis=1) print(df_2)
最终输出示例
两种方案都会得到如下结果:
| id | Expected_Salary | Salary_from_df_1 | id_from_df_1 |
|---|---|---|---|
| 1 | 9 | 10 | 1 |
| 2 | 49 | 50 | 5 |
| 3 | 18 | 20 | 2 |
| 4 | 19 | 20 | 2 |
| 5 | 29 | 30 | 3 |
| 6 | 41 | 40 | 4 |
| 7 | 4 | 10 | 1 |
| 8 | 57 | 50 | 5 |
| 9 | 42 | 40 | 4 |
| 10 | 3 | 10 | 1 |
内容的提问来源于stack exchange,提问作者NN_Developer
相关产品推荐
相关产品推荐

