如何在Python中用单个函数处理两个列表生成DataFrame新列
问题与解决方案
需求
- 在DataFrame中新增
Effect列,匹配逻辑分两步:- 优先匹配
lista中的元素,返回第一个出现的匹配项 - 若
lista无匹配,则匹配listb中的短语,返回第一个匹配的短语及其后续两个字符串
- 优先匹配
现有匹配列表
lista = ["A", "B", "C", "D"] listb = ["would not", "use to", "manage to", "when", "did not"]
用户尝试的代码
def matcher(Description): for i in lista: if i in Description: return i return "Not found" def matcher(Description): for j in listb: if j in Description: return j + 1 return "Not found" df["Effect"] = df.apply(lambda i: matcher(i["Description"]), axis=1) df["Effect"] = df.apply(lambda j: matcher(j["Description"]), axis=1)
代码问题分析
- 重复定义
matcher函数,第二个函数会完全覆盖第一个,导致永远只会执行listb的匹配逻辑,丢失了lista的优先匹配规则 return j + 1逻辑错误,这行代码只是把字符串和数字拼接,完全无法实现“返回匹配项及其后两个字符串”的需求- 两次对
df["Effect"]赋值,会直接覆盖第一次的结果,逻辑完全混乱
修正后的代码
def matcher(description): # 第一步:优先匹配lista中的元素 for item in lista: if item in description: return item # 第二步:lista无匹配时,处理listb的短语匹配 for phrase in listb: if phrase in description: # 将文本按空格分割为单词列表 words = description.split() phrase_words = phrase.split() phrase_len = len(phrase_words) # 遍历找到短语在单词列表中的起始位置 for idx in range(len(words) - phrase_len + 1): if words[idx:idx+phrase_len] == phrase_words: # 截取当前短语及后续最多两个单词,避免索引越界 end_pos = min(idx + phrase_len + 2, len(words)) return ' '.join(words[idx:end_pos]) # 无任何匹配时返回 return "Not found" # 仅需一次赋值即可完成逻辑 df["Effect"] = df.apply(lambda row: matcher(row["Description"]), axis=1)
代码说明
- 先执行
lista的匹配逻辑,确保优先级 - 处理
listb时,通过分割单词列表精准定位短语位置,避免直接字符串截取可能出现的歧义 - 使用
min函数处理索引边界,防止文本长度不足时抛出错误 - 仅一次
apply赋值,避免结果被覆盖
内容的提问来源于stack exchange,提问作者Victor Leon
相关产品推荐
相关产品推荐

