Pandas实现类Excel VLOOKUP:处理含NaN值的两个DataFrame匹配并避免行数翻倍
解决Pandas中类似Excel VLOOKUP的逐行匹配需求
我太懂你这种困扰了——想用Pandas实现Excel里VLOOKUP那种精准的逐行匹配,既要保留原DataFrame的所有行和列,又不能因为匹配操作导致行数莫名翻倍,对吧?针对你给出的df1和df2,我给你整理了完美的解决方案:
先还原你的数据
首先我们先把你提供的两个DataFrame用代码构造出来:
import pandas as pd import numpy as np # 构造df1 df1 = pd.DataFrame({ 'name': ['Hector ABC', 'Hector ABC', 'Jose JKD', 'Luis AH', 'Billy DH', 'Harry AC'], 'mobile_no': [123, 287, 567, np.nan, np.nan, 569] }) # 构造df2 df2 = pd.DataFrame({ 'download_date': ['2021-05-30', '2020-09-28', '2021-02-11', '2021-10-06', '2020-01-15'], 'mobile_no': [123, 287, 789, 321, 569] })
核心解决方案:用map实现类VLOOKUP匹配
直接用map方法就能实现你要的效果,它和Excel的VLOOKUP逻辑完全一致:按mobile_no的值精确匹配,返回对应的download_date,同时完整保留df1的所有行和列:
# 从df2创建「mobile_no → download_date」的映射关系 date_mapping = df2.set_index('mobile_no')['download_date'] # 给df1新增download_date列 df1['download_date'] = df1['mobile_no'].map(date_mapping)
运行后得到的结果完全符合你的预期:
| name | mobile_no | download_date | |
|---|---|---|---|
| 0 | Hector ABC | 123 | 2021-05-30 |
| 1 | Hector ABC | 287 | 2020-09-28 |
| 2 | Jose JKD | 567 | NaN |
| 3 | Luis AH | NaN | NaN |
| 4 | Billy DH | NaN | NaN |
| 5 | Harry AC | 569 | 2020-01-15 |
为什么你之前的方法没生效?
- 关于
np.where:你之前用的np.where(df1.mobile_no == df2.mobile_no, df2.download_date, np.nan)是逐行对比两个DataFrame的索引和mobile_no值,只有当两行索引相同且mobile_no相等时才会匹配,这不是我们要的「按值匹配」逻辑,所以自然得不到正确结果。 - 关于
pd.merge行数翻倍:如果直接用merge不做调整,当df2中存在重复的mobile_no时,会产生笛卡尔积导致行数暴涨。而map本质是一对一的映射,完全不会有这个问题。
特殊情况处理:如果df2有重复的mobile_no
如果你的实际数据中df2存在重复的mobile_no,可以先对df2去重(比如保留最新的下载日期),再创建映射:
# 按mobile_no去重,保留最新的download_date(可根据需求调整排序逻辑) df2_unique = df2.sort_values('download_date', ascending=False).drop_duplicates('mobile_no') date_mapping = df2_unique.set_index('mobile_no')['download_date'] df1['download_date'] = df1['mobile_no'].map(date_mapping)
内容的提问来源于stack exchange,提问作者JT-12
相关产品推荐
相关产品推荐

