You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按逻辑运算符与括号拆分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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 15:17:27