Python中如何实现字符串词级匹配并更新pandas DataFrame列值
实现方案
核心逻辑是先记录note_sentence中每个单词对应的字符起止偏移,再把正则匹配到的注解字符区间映射到对应词索引,最后修改标记列表即可。
完整实现代码
import pandas as pd import re def update_annotation_label(row): note_text = row['note_sentence'] anno_text = row['annotation'].strip() # 复制初始标签列表,避免修改原引用 label_list = row['listofsentence'].copy() # ------------ 第一步:记录每个单词的字符位置和词索引 ------------ word_span_list = [] # 注意:这里的单词拆分规则必须和你生成初始listofsentence的拆分规则完全一致,否则会出现索引错位 # 示例用正则匹配独立单词,如果你当初是按空格split拆分,替换成下方注释的空格拆分逻辑即可 for word_idx, word_match in enumerate(re.finditer(r'\b\w+\b', note_text)): word_span_list.append( (word_match.start(), word_match.end()) ) # 空格拆分版本的word_span_list生成逻辑: # cur_pos = 0 # for word in note_text.split(' '): # w_start = note_text.index(word, cur_pos) # w_end = w_start + len(word) # word_span_list.append( (w_start, w_end) ) # cur_pos = w_end if not anno_text: return label_list # ------------ 第二步:匹配所有注解片段的字符区间 ------------ # re.escape用于转义注解里的正则特殊字符,避免匹配报错 # 如果你需要严格全词匹配、不匹配长单词中的子串,把匹配规则改成 rf'\b{re.escape(anno_text)}\b' 即可 # 不需要忽略大小写就去掉flags参数 for anno_match in re.finditer(re.escape(anno_text), note_text, flags=re.IGNORECASE): m_start = anno_match.start() m_end = anno_match.end() # ------------ 第三步:把字符区间映射到词索引,更新标记 ------------ for word_idx, (w_start, w_end) in enumerate(word_span_list): # 只要单词和匹配区间有重叠就标记为I,可根据需求调整判定规则 if w_end > m_start and w_start < m_end: label_list[word_idx] = 'I' return label_list # 应用到整个DataFrame df['listofsentence'] = df.apply(update_annotation_label, axis=1)
关键注意事项
- 单词拆分规则必须和生成初始
listofsentence的规则完全统一,否则会出现词索引错位、标记位置不准的问题 - 如果注解文本包含标点、特殊符号,优先用和初始拆分逻辑一致的方式生成
word_span_list - 如果存在多段匹配的注解,代码会自动把所有命中位置的标记更新为'I',和示例效果一致
内容的提问来源于stack exchange,提问作者tanmay
相关产品推荐
相关产品推荐

