如何在Pandas中实现行级部分匹配?解决TypeError报错
Pandas行级单词匹配问题解决方法
问题说明
需要在Pandas DataFrame中实现行级部分匹配:判断每行name列的任意单词是否与对应行terms_list列表中的任意项匹配。
示例输入
name terms_list 0 acupuncturist [acupuncturist, acupuncture] 1 seafood restaurant [seafood, fish] 2 pet daycare [pet, dog, k9] 3 seafood restaurant [restaurant] 4 seafood grocery [restaurant]
期望输出
match 0 yes 1 yes 2 yes 3 yes 4 no
尝试的错误代码及报错
执行以下代码时触发报错:
df_x[df_x.apply(lambda x: df_x['name'] in df_x['terms_list'], axis=1)]
报错信息:TypeError: unhashable type: 'Series'
可复现代码
df = pd.DataFrame({'name': ['acupuncturist', 'seafood restaurant', 'pet daycare', 'seafood restaurant', 'seafood grocery'], 'terms_list': [['acupuncturist', 'acupuncture'], ['seafood', 'fish'], ['pet', 'dog', 'k9'], ['restaurant'], ['restaurant']] })
错误原因
你写的lambda里误用了整个DataFrame的Series(df_x['name']、df_x['terms_list']),而不是当前行的单个值。而且没把name拆分成单个单词,直接拿整串去和列表比对,逻辑本身也不对。
解决方法
方法一:修正apply逻辑(适合小数据集)
先把每行的name拆成单词集合,再和terms_list的集合求交集,判断是否有重叠:
def check_match(row): # 拆分name为单词集合,terms_list转为集合 name_words = set(row['name'].split()) term_set = set(row['terms_list']) # 有交集则返回yes,否则no return 'yes' if name_words & term_set else 'no' # 生成match列 df['match'] = df.apply(check_match, axis=1)
方法二:向量化实现(推荐,大数据量更高效)
apply是逐行遍历,数据量大时效率低,用Pandas的向量化操作来优化:
# 把name拆成单个单词,保留原行索引 name_words = df['name'].str.split(expand=True).stack().reset_index(level=1, drop=True).rename('word') # 把terms_list拆成单个元素,保留原行索引 terms = df['terms_list'].explode().rename('term') # 按行分组,判断当前行是否有单词在对应行的terms里 row_matches = name_words.isin(terms.groupby(level=0).unique()).groupby(level=0).any() # 转换为yes/no格式 df['match'] = row_matches.map({True: 'yes', False: 'no'})
验证结果
运行后df['match']的输出和期望完全一致:
0 yes 1 yes 2 yes 3 yes 4 no Name: match, dtype: object
内容的提问来源于stack exchange,提问作者Dutt
相关产品推荐
相关产品推荐

