
本文介绍在 pandas 中实现非标准列名/值对齐的条件合并:当两表无直接等值键但需根据“vintage 字段是否被 service 字符串包含”且 deliveryperiod 完全匹配时,关联并填充 floatprice,未匹配项设为 0.0。
本文介绍在 pandas 中实现非标准列名/值对齐的条件合并:当两表无直接等值键但需根据“vintage 字段是否被 service 字符串包含”且 deliveryperiod 完全匹配时,关联并填充 floatprice,未匹配项设为 0.0。
在实际数据分析中,常遇到两个 DataFrame 的关联逻辑无法通过简单 merge(on=...) 实现的情况——例如本例中,df1['Vintage'] 与 df2['Service'] 并非精确相等,而是存在「子字符串包含」关系(如 "Vintage 2025" 出现在 "ICE - Vintage 2025" 中),同时还需满足 DeliveryPeriod 完全一致。此时需分步处理:先基于强匹配字段粗联,再用布尔逻辑精细化过滤。
推荐做法如下:
-
以
DeliveryPeriod为键执行左连接(保留df1全部行); -
构造布尔掩码,逐行判断
Vintage是否为非空字符串且被Service包含; -
将不满足条件的
FloatPrice替换为0.00,并删除冗余的Service列。
import pandas as pd
# 示例数据构建(便于复现)
df1 = pd.DataFrame({
'BA': ['A', 'B', 'B', 'C'],
'Product': ['foo', 'foo', 'foo', 'bar'],
'FixedPrice': [10.00, 11.00, 12.00, 2.00],
'Vintage': ['Vintage 2025', 'Vintage 2025', 'Vintage 2024', 'None'],
'DeliveryPeriod': ['Mar25', 'Dec25', 'Sep25', 'Nov25']
})
df2 = pd.DataFrame({
'Service': ['ICE - Vintage 2025', 'ICE - Vintage 2025',
'ICE - Vintage 2024', 'ICE - Vintage 2023'],
'DeliveryPeriod': ['Mar25', 'Dec25', 'Sep25', 'Nov25'],
'FloatPrice': [5.00, 4.00, 6.00, 1.00]
})
# 步骤1:基于 DeliveryPeriod 左连接
df_merge = df1.merge(df2, on='DeliveryPeriod', how='left')
# 步骤2:生成匹配掩码(注意处理 None/Vintage='None' 等边界情况)
mask = df_merge.apply(
lambda row: (
isinstance(row['Vintage'], str) and
row['Vintage'] != 'None' and
row['Vintage'] in row['Service']
),
axis=1
)
# 步骤3:不匹配处 FloatPrice 置 0.00,并清理列
df_merge.loc[~mask, 'FloatPrice'] = 0.00
df_merge = df_merge.drop(columns=['Service'])
print(df_merge)✅ 输出结果与预期一致:
BA Product FixedPrice Vintage DeliveryPeriod FloatPrice 0 A foo 10.0 Vintage 2025 Mar25 5.0 1 B foo 11.0 Vintage 2025 Dec25 4.0 2 B foo 12.0 Vintage 2024 Sep25 6.0 3 C bar 2.0 None Nov25 0.0
⚠️ 注意事项:
-
apply(axis=1)是清晰易懂的方案,但对超大数据集可能较慢;若追求性能,可预处理df2,提取Vintage子串并构造映射字典(如{'Mar25': {'Vintage 2025': 5.0}}),再用map加速; -
Vintage == 'None'需显式排除,避免误判为子串匹配; - 若
Vintage列含缺失值(NaN),isinstance(..., str)自动返回False,安全可靠; - 最终
FloatPrice类型保持float64,便于后续数值计算。
该方法兼顾可读性与鲁棒性,适用于大多数「语义关联而非精确键匹配」的业务场景。

















