基于Pandas数据框匹配ID替换表达式取值并计算结果的实现问题
Pandas表达式ID替换冲突问题解决方法
核心问题原因
原有实现采用全局子串替换逻辑,纯数字ID会匹配到组合ID中的数字片段,导致替换错误。
解决思路
使用正则断言做完整ID匹配,仅替换前后无其他字母/数字的独立ID,同时按ID长度倒序替换,避免短ID干扰长ID匹配。
完整实现代码
import pandas as pd import re # 入参定义 # df:包含Patient、ID两列的原始数据框 exp = '((71+72)*((73+75)+SD75))*((74+76)+SD76))' # 步骤1:提取表达式中所有ID,按长度倒序排序 all_exp_ids = re.findall(r'[A-Za-z]*\d+', exp) all_exp_ids = sorted(list(set(all_exp_ids)), key=lambda x: len(x), reverse=True) # 步骤2:构建患者ID映射表 patient_id_set = df.groupby('Patient')['ID'].agg(set).to_dict() # 步骤3:定义单患者结果计算逻辑 def calculate_value(patient): owned_ids = patient_id_set[patient] processed_exp = exp for id_val in all_exp_ids: # 前后断言保证仅匹配独立ID,不匹配子串 pattern = re.compile(rf'(?<![0-9a-zA-Z]){re.escape(id_val)}(?![0-9a-zA-Z])') processed_exp = pattern.sub('1' if id_val in owned_ids else '0', processed_exp) return eval(processed_exp) # 步骤4:生成结果表 result_df = pd.DataFrame({ 'Patient': patient_id_set.keys() }) result_df['FinalVal'] = result_df['Patient'].apply(calculate_value)
关键逻辑说明
- 正则匹配规则中
(?<![0-9a-zA-Z])和(?![0-9a-zA-Z])为前后负向断言,保证匹配到的ID前后没有其他字母、数字字符,因此75只会匹配独立出现的数字75,不会匹配SD75中的数字片段。 - ID按长度倒序排序是为了避免短ID优先替换后破坏长ID的结构,比如同时存在
7和75时,先替换75再替换7不会出现匹配冲突。 - 若表达式来源不可信,可将
eval替换为ast.literal_eval规避安全风险。
内容的提问来源于stack exchange,提问作者user3234112
相关产品推荐
相关产品推荐

