如何基于多条件和动态概率对两个DataFrame执行三次左连接
基于Pandas的实现方案
默认你使用Python Pandas处理数据框,其他工具的实现逻辑可以参考该思路调整。
前置假设
- DF B包含用于抽取的数值列,列名为
b_val - 你可以根据自身业务需求修改自定义概率的计算逻辑,示例中的概率为参考你的需求预设,可自行调整
核心实现代码
import pandas as pd import numpy as np # ---------------------- 1. 准备示例数据,可替换为真实数据 ---------------------- # 构造DF A df_a = pd.DataFrame({ 'amount': [120, 80, 150, 90] }) # 构造DF B df_b = pd.DataFrame({ 'b_val': [80,90,100,110,120,130,140,150,160,170,999] }) b_values = df_b['b_val'].tolist() # ---------------------- 2. 定义自定义概率抽取函数 ---------------------- def sample_a_col(amount, b_vals): # 筛选<=amount的候选值 candidates = [v for v in b_vals if v <= amount] if not candidates: return np.nan # 无候选值时返回空,可根据需求调整 # 自定义概率:可自行修改键值对匹配业务规则 prob_map = { 120:0.2, 110:0.05, 100:0.5, 90:0.1, 80:0.15 } # 按候选值匹配权重,无匹配项默认均分权重 probs = [prob_map.get(v, 1/len(candidates)) for v in candidates] # 权重归一化避免总和不为1 probs = np.array(probs) / sum(probs) return np.random.choice(candidates, p=probs) def sample_b_col(amount, b_vals): # 筛选>amount且不等于999的候选值 candidates = [v for v in b_vals if v > amount and v != 999] if not candidates: return np.nan # 自定义概率:可自行修改键值对匹配业务规则 prob_map = { 130:0.2,140:0.05,150:0.5,160:0.1,170:0.15 } probs = [prob_map.get(v, 1/len(candidates)) for v in candidates] probs = np.array(probs) / sum(probs) return np.random.choice(candidates, p=probs) # ---------------------- 3. 给DF A赋值三个列 ---------------------- df_a['A'] = df_a['amount'].apply(lambda x: sample_a_col(x, b_values)) df_a['B'] = df_a['amount'].apply(lambda x: sample_b_col(x, b_values)) df_a['C'] = 999 # 输出结果 print(df_a)
逻辑说明
- 如果自定义概率需要按动态规则生成(比如距离amount越近权重越高),可以直接替换两个抽取函数中
prob的生成逻辑 - 如果数据量很大(百万行以上),可以把逐行
apply改成预分组处理:先把DF A按amount分组,每组统一抽取候选值,性能提升会非常明显 - 需求中提到的三次左连接本质是按不同条件匹配DF B的候选值,上述实现已经覆盖了所有匹配规则,不需要显式写三次
merge操作,性能更高
内容的提问来源于stack exchange,提问作者ABC
相关产品推荐
相关产品推荐

