如何基于关键词匹配与供应商校验填充Pandas DataFrame的Company.1列
问题背景
我有两个DataFrame:
df1
data1 = { 'Company': ['ADIDAS', 'NIKE', 'PUMA', 'NEW BALANCE', 'UNDER ARMOUR'], 'Keywords': ['COPA, PREDATOR, ORIGINALS, SPEEDFLOW', 'MERCURIAL, SUPERSTAR, VAPOR', 'ULTRA, FUTURE, RAPIDO', 'FURON', 'TEKELA'], 'Suppliers': ['', '', '[STADIUM, JD]', '', ''] }
| Company | Keywords | Suppliers |
|---|---|---|
| ADIDAS | [COPA, PREDATOR, ORIGINALS, SPEEDFLOW] | |
| NIKE | [MERCURIAL, SUPERSTAR, VAPOR] | |
| PUMA | [ULTRA, FUTURE, RAPIDO] | [STADIUM, JD] |
| NEW BALANCE | [FURON] | |
| UNDER ARMOUR | [TEKELA] |
df2
data2 = { 'Names': ['ADIDAS PREDATOR 17.1', 'NIKE MERCURIAL 2020', 'NIKE VAPOR 2021', 'NEW BALANCE FURON', 'PUMA RAPIDO 21.3', 'PUMA RAPIDO 21.4'], 'Supplier': ['ADIDAS', 'NIKE', 'NIKE', 'JD', 'STADIUM', 'JD'], 'Company.1': ['', '', '', '', '', ''] }
| Names | Supplier | Company.1 |
|---|---|---|
| ADIDAS PREDATOR 17.1 | ADIDAS | |
| NIKE MERCURIAL 2020 | NIKE | |
| NIKE VAPOR 2021 | NIKE | |
| NEW BALANCE FURON | JD | |
| PUMA RAPIDO 21.3 | STADIUM | |
| PUMA RAPIDO 21.4 | JD |
目标
检查df2['Names']是否包含df1['Keywords']中的任意词汇,若包含则校验df1['Suppliers']与df2['Supplier']是否匹配(若df1['Suppliers']为空则无需校验供应商),符合条件则将df2['Company.1']赋值为对应的df1['Company']。
已尝试代码
for i in range(len(df1["Keywords"])): for j in range(len(df1["Keywords"][i])): for name_index in range(len(df2["Product_name"])): if df1["Keywords"][i][j].strip() in df2["Product_name"][name_index]: print("YES " + df1["Keywords"][i][j] + " in "+ df2["Product_name"][name_index]) # Now need to check if suppliers are same
预期输出
| Names | Supplier | Company.1 |
|---|---|---|
| ADIDAS PREDATOR 17.1 | ADIDAS | ADIDAS |
| NIKE MERCURIAL 2020 | NIKE | NIKE |
| NIKE VAPOR 2021 | NIKE | NIKE |
| NEW BALANCE FURON | JD | NEW BALANCE |
| PUMA RAPIDO 21.3 | STADIUM | PUMA |
问题
如何根据满足的条件为df2['Company.1']添加对应的公司名称?
解决方案
步骤1:预处理df1字段
先把df1中的Keywords和Suppliers字符串转为列表,方便后续匹配:
import pandas as pd # 初始化DataFrame df1 = pd.DataFrame(data1) df2 = pd.DataFrame(data2) # 处理Keywords:分割字符串为列表并去除空格 df1['Keywords'] = df1['Keywords'].apply(lambda x: [k.strip() for k in x.split(',')]) # 处理Suppliers:空值/空字符串转为空列表,非空则解析为供应商列表 def process_suppliers(s): if pd.isna(s) or s.strip() == '' or s == '<NA>': return [] # 去除首尾方括号后分割 s_clean = s.strip('[]') return [sup.strip() for sup in s_clean.split(',')] df1['Suppliers'] = df1['Suppliers'].apply(process_suppliers)
步骤2:编写匹配逻辑函数
对df2的每一行执行匹配判断:
def match_company(row): name = row['Names'] supplier = row['Supplier'] for _, df1_row in df1.iterrows(): company = df1_row['Company'] keywords = df1_row['Keywords'] suppliers = df1_row['Suppliers'] # 检查名称是否包含任意关键词 has_keyword = any(keyword in name for keyword in keywords) if not has_keyword: continue # 校验供应商:若df1无供应商要求则直接匹配,否则检查当前供应商在列表内 if not suppliers or supplier in suppliers: return company # 无匹配项返回空 return '' # 应用函数填充Company.1 df2['Company.1'] = df2.apply(match_company, axis=1) # 过滤未匹配的行(和预期输出一致) df2 = df2[df2['Company.1'] != ''].reset_index(drop=True)
运行结果
执行后df2的输出与预期完全一致:
| Names | Supplier | Company.1 |
|---|---|---|
| ADIDAS PREDATOR 17.1 | ADIDAS | ADIDAS |
| NIKE MERCURIAL 2020 | NIKE | NIKE |
| NIKE VAPOR 2021 | NIKE | NIKE |
| NEW BALANCE FURON | JD | NEW BALANCE |
| PUMA RAPIDO 21.3 | STADIUM | PUMA |
说明
- 相比嵌套循环,用
apply结合iterrows的写法更简洁易读,符合pandas的使用习惯 - 预处理字段统一转为列表,避免了重复的字符串操作
- 逻辑分层清晰:先匹配关键词,再按需校验供应商,匹配到第一个符合条件的公司立即返回
内容的提问来源于stack exchange,提问作者Roshan
相关产品推荐
相关产品推荐

