Python-Pandas技术问询:在单元格中搜索关键词并基于关键词取值
提问:如何在Pandas单元格的字符串中搜索关键词,并根据匹配的关键词提取对应值?
我现在有一个包含文本数据的Pandas DataFrame,其中某一列的单元格是较长的字符串,里面可能包含我预设的若干关键词。我想要实现的是:遍历这一列的每个单元格,检查字符串中是否存在指定的关键词,然后根据匹配到的关键词返回对应的预设值。
举个例子,我的DataFrame大概是这样的:
| 序号 | 描述文本 |
|---|---|
| 1 | 这是一篇关于Python的教程文章 |
| 2 | Pandas数据处理技巧分享 |
| 3 | Python与Pandas实战案例解析 |
| 4 | Java开发入门指南 |
我有一个关键词-值的映射表:
keyword_map = { "Python": "编程语言", "Pandas": "数据工具", "Java": "编程语言" }
我希望能新增一列“分类”,根据“描述文本”中包含的关键词填充对应的分类值,如果有多个关键词匹配(比如第3行同时包含Python和Pandas),可以返回第一个匹配的值或者合并值。请问有没有高效的实现方法?
解答
嗨,我来帮你搞定这个问题!针对你说的在Pandas单元格字符串里搜索关键词并映射对应值的需求,我整理了几种实用的方法,结合你的示例一步步给你说明:
方法一:使用str.contains结合numpy.select(适合多关键词优先级匹配)
这种方法适合你需要给关键词设定匹配优先级的场景——比如你想优先匹配Python,再匹配Pandas,那即使单元格里同时有两个关键词,也会返回优先级高的那个对应值:
import pandas as pd import numpy as np # 构造示例DataFrame df = pd.DataFrame({ "序号": [1,2,3,4], "描述文本": ["这是一篇关于Python的教程文章", "Pandas数据处理技巧分享", "Python与Pandas实战案例解析", "Java开发入门指南"] }) # 关键词-值映射 keyword_map = { "Python": "编程语言", "Pandas": "数据工具", "Java": "编程语言" } # 提取关键词列表和对应的值列表,注意顺序就是匹配优先级 keywords = list(keyword_map.keys()) values = list(keyword_map.values()) # 创建匹配条件列表:每个关键词对应一个str.contains的布尔数组,case=False忽略大小写 conditions = [df["描述文本"].str.contains(key, case=False) for key in keywords] # 使用numpy.select匹配,没有匹配到的设为"未分类" df["分类"] = np.select(conditions, values, default="未分类") print(df)
运行后输出的结果:
序号 描述文本 分类 0 1 这是一篇关于Python的教程文章 编程语言 1 2 Pandas数据处理技巧分享 数据工具 2 3 Python与Pandas实战案例解析 编程语言 3 4 Java开发入门指南 编程语言
方法二:使用apply自定义函数(适合灵活处理多关键词合并)
如果想要把所有匹配到的关键词对应的分类合并展示(比如第3行同时返回“编程语言,数据工具”),用apply结合自定义函数就很灵活:
def get_category(text): categories = set() for key, val in keyword_map.items(): if key in text: categories.add(val) return ",".join(categories) if categories else "未分类" df["分类"] = df["描述文本"].apply(get_category) print(df)
输出结果:
序号 描述文本 分类 0 1 这是一篇关于Python的教程文章 编程语言 1 2 Pandas数据处理技巧分享 数据工具 2 3 Python与Pandas实战案例解析 编程语言,数据工具 3 4 Java开发入门指南 编程语言
方法三:使用str.extract提取关键词再映射(适合精准提取关键词)
如果你的关键词都是独立的词汇,也可以先提取出匹配的关键词,再用map映射对应值,这种方式能清晰看到匹配到的具体关键词:
import re # 用正则表达式匹配所有关键词,|分隔表示或,re.escape处理关键词里的特殊字符 pattern = "|".join(re.escape(key) for key in keywords) # 提取第一个匹配的关键词,flags=re.IGNORECASE忽略大小写 df["匹配关键词"] = df["描述文本"].str.extract(f'({pattern})', flags=re.IGNORECASE)[0] # 映射分类值,空值填充"未分类" df["分类"] = df["匹配关键词"].map(keyword_map).fillna("未分类") print(df)
一些额外提示:
- 如果你担心关键词的大小写问题,记得在
str.contains或者正则里加上忽略大小写的参数(比如case=False、flags=re.IGNORECASE) - 如果你的数据集很大,
apply的效率会比矢量化的str.contains+numpy.select低,优先选择矢量化方法 - 要是关键词里包含正则特殊字符(比如
.、*、+),一定要用re.escape()转义,避免正则匹配出错
内容的提问来源于stack exchange,提问作者Andrew Shoe
相关产品推荐
相关产品推荐

