DataFrame中Pests列值为'None'时从FieldComment提取指定词填充
解决DataFrame中Pests列的批量匹配替换问题
需求说明
我有一个包含Pests和FieldComment两列的DataFrame,需要实现:当Pests列值为'None'时,在对应行的FieldComment中搜索指定虫害词汇,找到匹配项则覆盖Pests列内容;未找到匹配项则保留'None'。
示例数据
指定虫害列表:
pests_list = ['Spiders', 'Rodents', 'Ants', 'Honey Bees']
原始DataFrame:
| Pests | FieldComment |
|---|---|
| Spiders | Performed service. |
| None | Performed service for reported rodents. |
理想结果
| Pests | FieldComment |
|---|---|
| Spiders | Performed service. |
| Rodents | Performed service for reported rodents. |
错误代码分析
你尝试的三段代码存在以下问题:
- 第一段代码
for w in df['FieldComment'].str.split(): for p in pests_list: if w.str.lower() == p.str.lower(): df['Pests'] = p
df['FieldComment'].str.split()返回的是Series,遍历后w是单个单元格的字符串列表,无法调用str.lower()方法;- 直接赋值
df['Pests'] = p会覆盖整列,而非对应匹配的行。
- 第二段代码
df.loc[df['Pests'] == 'None', "Pests"] = *[pest for pest in pest_list if pest in df['FieldComment']]
- 语法错误,
*不能直接用于赋值语句的右侧; pest in df['FieldComment']是检查虫害是否存在于整个FieldComment列,而非当前行的内容。
- 第三段代码
df.loc[df['Pests'] == 'None', "Pests"] = df.loc[df['Pests'] == 'None', "Pests"].apply(lambda x: pest for pest in pest_list if pest in df['FieldComment'] else 'None')
- lambda表达式返回的是生成器对象,而非具体匹配值;
df['FieldComment']指向整个列,不是当前行的FieldComment内容;apply的参数x是Pests列的值,和FieldComment无关。
正确解决方案
方法一:逐行匹配(灵活易读)
使用apply逐行处理,自定义匹配逻辑:
import pandas as pd pests_list = ['Spiders', 'Rodents', 'Ants', 'Honey Bees'] df = pd.DataFrame({ 'Pests': ['Spiders', 'None'], 'FieldComment': ['Performed service.', 'Performed service for reported rodents.'] }) def match_pest(row): # 非None值直接保留 if row['Pests'] != 'None': return row['Pests'] # 转换为小写,避免大小写匹配问题 comment_lower = row['FieldComment'].lower() for pest in pests_list: if pest.lower() in comment_lower: return pest # 无匹配项保留None return 'None' # 应用函数到每一行 df['Pests'] = df.apply(match_pest, axis=1)
方法二:正则提取(高效简洁)
利用正则表达式批量提取匹配项,适合大数据量场景:
import pandas as pd import re pests_list = ['Spiders', 'Rodents', 'Ants', 'Honey Bees'] df = pd.DataFrame({ 'Pests': ['Spiders', 'None'], 'FieldComment': ['Performed service.', 'Performed service for reported rodents.'] }) # 构建匹配正则:匹配列表中任意虫害词汇 pest_pattern = '|'.join(pests_list) # 筛选Pests为None的行 mask = df['Pests'] == 'None' # 提取匹配项,忽略大小写,无匹配则填充None df.loc[mask, 'Pests'] = df.loc[mask, 'FieldComment'].str.extract( f'({pest_pattern})', flags=re.IGNORECASE ).fillna('None')
内容的提问来源于stack exchange,提问作者Ernie Redfield
相关产品推荐
相关产品推荐

