如何按逻辑运算符与括号拆分Pandas DataFrame约束条件
问题描述
我有一个包含Component列和Constraint列的Pandas DataFrame,约束条件是带AND、OR运算符及括号的复杂逻辑表达式,需要将其拆分为多条简洁的约束行(比如把A and (B or C)拆成A and B和A and C)。
示例数据
import pandas as pd dataex = {'Component': [123, 456, 789], 'Constraint': ["A and (B or C)", "((MIRROR='ELECTRIC' and MIRRORCAMERA!='NO') or (MIRROR='MANUAL' and (MIRROR_RIGHT!='NO' or MIRROR_LEFT!='NO'))) and STEERWHEEL_LOCK='NO'", "LENGTH='122' or (LENGTH='135' and BATTERY='551') or LENGTH='149' or (LENGTH='181' and (BATTERY='674' or (BATTERY='551' and CHARGER!='NO')))"]} df_example = pd.DataFrame(data=dataex)
期望结果
import pandas as pd datares = {'Component':[123, 123, 456, 456, 456, 789, 789, 789, 789, 789], 'Constraint':["A and B", "A and C", "STEERWHEEL_LOCK='NO' and MIRROR='ELECTRIC' and MIRRORCAMERA!='NO'", "STEERWHEEL_LOCK='NO' and MIRROR='MANUAL' and MIRROR_RIGHT!='NO'", "STEERWHEEL_LOCK='NO' and MIRROR='MANUAL' and MIRROR_LEFT!='NO'", "LENGTH='122'", "LENGTH='135' and BATTERY='551'", "LENGTH='149'", "LENGTH='181' and BATTERY='674'", "LENGTH='181' and BATTERY='551' and CHARGER!='NO'" ]} df_result = pd.DataFrame(data=datares)
之前尝试按OR拆分后循环处理,但嵌套结构导致逻辑混乱;试过构建逻辑树但没在Python中实现,求可行方案或适用模块。
解决方案
可以使用pyparsing库解析嵌套逻辑表达式,递归展开OR运算符,将复杂表达式转换为多个AND组合的约束行,具体实现如下:
步骤1:安装依赖
如果未安装pyparsing,先执行:
pip install pyparsing
步骤2:编写解析与展开函数
import pandas as pd from pyparsing import Word, alphas, nums, QuotedString, infixNotation, opAssoc, ParserElement # 启用快速解析优化 ParserElement.enablePackrat() # 匹配约束中的原子条件(比如A、MIRROR='ELECTRIC'等) atom = (QuotedString("'") | Word(alphas + nums + "_=!<>")) # 定义逻辑运算符的优先级和结合性 expr = infixNotation(atom, [ ("and", 2, opAssoc.LEFT), ("or", 2, opAssoc.LEFT), ]) def flatten_expression(expr_tree): # 递归展开OR表达式,返回所有AND组合的列表 if isinstance(expr_tree, str): return [[expr_tree]] if expr_tree[0] == 'and': left = flatten_expression(expr_tree[1]) right = flatten_expression(expr_tree[2]) # 合并左右两边的AND条件项 return [l + r for l in left for r in right] elif expr_tree[0] == 'or': left = flatten_expression(expr_tree[1]) right = flatten_expression(expr_tree[2]) # 合并左右两边的OR分支 return left + right else: return [[expr_tree]] def process_constraint(constraint_str): # 解析约束字符串为语法树,展开后转换为约束行字符串 parsed = expr.parseString(constraint_str, parseAll=True)[0] flattened = flatten_expression(parsed) return [" and ".join(terms) for terms in flattened]
步骤3:处理DataFrame生成结果
# 处理示例DataFrame result_rows = [] for idx, row in df_example.iterrows(): comp = row['Component'] expanded_constraints = process_constraint(row['Constraint']) for cons in expanded_constraints: result_rows.append({'Component': comp, 'Constraint': cons}) df_result = pd.DataFrame(result_rows) print(df_result)
运行后即可得到与示例一致的拆分结果。
说明
pyparsing负责解析带嵌套括号的逻辑表达式,生成结构化语法树,避免手动拆分字符串的逻辑混乱;flatten_expression函数递归处理语法树:遇到OR就拆分分支,遇到AND就合并条件项,最终得到所有独立的AND约束组合;- 该方法支持任意深度的嵌套结构,比手动拆分更稳定可靠。
内容的提问来源于stack exchange,提问作者EindbaasJohn
相关产品推荐
相关产品推荐

