如何通过字典指定pandas DataFrame过滤规则 支持大于小于等复杂操作
可行实现方案
第一步:定义标准化的JSON过滤规则结构
采用支持嵌套的规则结构,既可以处理普通单条件,也可以实现与/或组合的复杂逻辑,规则示例如下:
{ "logic": "and", "conditions": [ {"col": "A", "op": ">", "value": 5}, {"col": "B", "op": "in", "value": [1,5,9]}, {"col": "C", "op": "==", "value": "blue"}, { "logic": "or", "conditions": [ {"col": "A", "op": "<", "value": 5}, {"col": "A", "op": ">", "value": 10} ] } ] }
- 顶层和嵌套块都用
logic指定当前层级的条件连接逻辑,支持and/or - 普通条件包含三个必填字段:列名
col、运算符op、对比值value
第二步:实现运算符映射与条件解析函数
预先定义支持的运算符映射,避免直接执行字符串带来的安全风险,同时支持后续灵活扩展新运算符:
import operator import pandas as pd # 运算符映射表,可按需新增自定义规则 OPERATOR_MAP = { '==': operator.eq, '!=': operator.ne, '>': operator.gt, '<': operator.lt, '>=': operator.ge, '<=': operator.le, 'in': lambda s, v: s.isin(v), 'not in': lambda s, v: ~s.isin(v), 'contains': lambda s, v: s.str.contains(v, na=False) } def parse_filter(df: pd.DataFrame, filter_rule: dict) -> pd.Series: """递归解析过滤规则,返回布尔序列供loc筛选""" logic = filter_rule.get('logic', 'and').lower() conditions = filter_rule['conditions'] bool_series = [] for cond in conditions: # 处理嵌套的逻辑块 if 'logic' in cond and 'conditions' in cond: bool_series.append(parse_filter(df, cond)) continue # 处理普通单条件 col = cond['col'] op = cond['op'] value = cond['value'] op_func = OPERATOR_MAP[op] bool_series.append(op_func(df[col], value)) # 按逻辑符合并所有条件 if logic == 'and': result = bool_series[0] for s in bool_series[1:]: result = result & s return result elif logic == 'or': result = bool_series[0] for s in bool_series[1:]: result = result | s return result else: raise ValueError(f"不支持的逻辑运算符: {logic}")
第三步:调用逻辑示例
接收bash传入的JSON参数,完成过滤:
import json import sys # 从bash参数读取过滤规则字符串,转成字典 filter_rule = json.loads(sys.argv[1]) # 生成过滤掩码 mask = parse_filter(df, filter_rule) # 得到结果 filtered_df = df.loc[mask]
额外说明
- 安全性:全程没有使用
eval执行任意字符串,仅允许使用预设的运算符,避免恶意代码注入风险,适合公共代码库使用 - 扩展性:后续需要新增过滤逻辑时,仅需要在
OPERATOR_MAP中添加对应的运算符和实现函数即可,不需要修改核心解析逻辑 - bash传参注意:传递JSON字符串时需要用单引号包裹,避免特殊字符被bash解析,示例调用命令:
bash your_script.sh '{"logic":"and","conditions":[{"col":"A","op":">","value":5},{"col":"B","op":"in","value":[1,5,9]}]}'
内容的提问来源于stack exchange,提问作者Julia Maddalena
相关产品推荐
相关产品推荐

