Pandas匹配数组列关联值返回NaN的问题排查与实现
原代码存在的问题
- 基础语法错误:列名未加字符串引号,
df1[some_id]应写为df1['some_id'];df2['some_ids'缺少闭合的右方括号,属于语法书写疏漏。 - 核心逻辑错误:
pandas.Series.isin()的作用是判断Series中每个元素,是否存在于传入的可迭代容器的顶层元素中。你传入的df2['some_ids']的顶层元素是三个列表[1,2]、[3,4]、[5],相当于拿整数类型的id去和列表类型的顶层元素做相等判断,永远无法匹配成功,因此筛选结果为空,赋值后自然全为NaN。
正确实现方案
优先使用explode展开数组列做关联的写法,性能更好、写法更符合pandas规范,适配大数据量场景:
import pandas as pd # 构造样例数据 df1 = pd.DataFrame({"some_id": [1, 2, 3, 4, 5]}) df2 = pd.DataFrame([["A", [1, 2]], ["B", [3, 4]], ["C", [5]]], columns=['letter', 'some_ids']) # 将数组列拆分为每行单个id的长表格式 df2_expand = df2.explode('some_ids', ignore_index=True) # 左连接匹配对应letter值 df1 = df1.merge( df2_expand[['letter', 'some_ids']], left_on='some_id', right_on='some_ids', how='left' ).drop(columns='some_ids')
执行后df1输出结果如下:
| some_id | letter |
|---|---|
| 1 | A |
| 2 | A |
| 3 | B |
| 4 | B |
| 5 | C |
如果数据量很小,也可以用构造映射字典的方式实现,逻辑更直观:
# 构建id到letter的映射关系 id_2_letter = {} for _, item in df2.iterrows(): for single_id in item['some_ids']: id_2_letter[single_id] = item['letter'] # 直接映射取值 df1['letter'] = df1['some_id'].map(id_2_letter)
内容的提问来源于stack exchange,提问作者funkurlif3
相关产品推荐
相关产品推荐

