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

如何基于多条件从另一DataFrame中提取指定数值?

解决方案:基于多条件匹配提取DataFrame对应字段

先明确条件规则

从样本数据来看,CONSTRUCTION_TYPE_FAMILY和CONSTRUCTION_TYPE的条件分为三类:

  • 正向匹配:用OR连接多个值,满足任意一个即符合条件
  • 反向排除:以Not/NOT:开头,需排除列表内的所有值
  • 模糊匹配:如H3xx代表匹配以H3开头的任意字符串

步骤1:编写条件解析工具函数

先实现两个辅助函数,用来拆解复杂的条件字符串:

import re

def parse_family_condition(condition_str):
    """解析CONSTRUCTION_TYPE_FAMILY条件,返回正向匹配列表、排除列表、模糊匹配正则"""
    # 清理多余引号和首尾空格
    cleaned = re.sub(r'["\'“”‘’]', '', condition_str.strip())
    include = []
    exclude = []
    fuzzy_patterns = []
    
    if cleaned.startswith("NOT:"):
        # 处理排除规则
        exclude_items = [item.strip() for item in cleaned[4:].split(',')]
        for item in exclude_items:
            if 'xx' in item:
                # 把xx替换为任意字符的正则
                fuzzy_patterns.append(re.compile(f"^{item.replace('xx', '.*')}$", re.IGNORECASE))
            else:
                exclude.append(item)
    else:
        # 处理OR连接的正向规则
        include_items = [item.strip() for item in cleaned.split('OR')]
        for item in include_items:
            if 'xx' in item:
                fuzzy_patterns.append(re.compile(f"^{item.replace('xx', '.*')}$", re.IGNORECASE))
            else:
                include.append(item)
    return include, exclude, fuzzy_patterns

def parse_type_condition(condition_str):
    """解析CONSTRUCTION_TYPE条件,返回是否为排除规则、目标匹配字符串"""
    cleaned = condition_str.strip()
    is_exclude = False
    target = ""
    if cleaned.startswith("Not "):
        is_exclude = True
        target = re.sub(r'["\'“”‘’]', '', cleaned[4:].strip())
    else:
        target = re.sub(r'["\'“”‘’]', '', cleaned)
    return is_exclude, target

步骤2:编写行匹配逻辑

针对DataFrame B的每一行,匹配DataFrame A中符合所有条件的记录:

import pandas as pd

def match_equipment(b_row, df_a):
    # 1. 先匹配CONSTRUCTOR(默认精确匹配,需模糊匹配可改成str.contains)
    filtered_a = df_a[df_a['CONSTRUCTOR'] == b_row['CONSTRUCTOR']]
    if filtered_a.empty:
        return pd.Series([None, None])
    
    # 2. 处理CONSTRUCTION_TYPE条件
    type_is_exclude, type_target = parse_type_condition(b_row['CONSTRUCTION_TYPE'])
    if type_is_exclude:
        filtered_a = filtered_a[~filtered_a['CONSTRUCTION_TYPE'].str.contains(type_target, na=False)]
    else:
        filtered_a = filtered_a[filtered_a['CONSTRUCTION_TYPE'].str.contains(type_target, na=False)]
    if filtered_a.empty:
        return pd.Series([None, None])
    
    # 3. 处理CONSTRUCTION_TYPE_FAMILY条件
    family_include, family_exclude, family_fuzzy = parse_family_condition(b_row['CONSTRUCTION_TYPE_FAMILY'])
    # 正向匹配:命中include列表 或 匹配模糊正则
    include_mask = filtered_a['CONSTRUCTION_TYPE_FAMILY'].isin(family_include)
    for pattern in family_fuzzy:
        include_mask |= filtered_a['CONSTRUCTION_TYPE_FAMILY'].str.match(pattern, na=False)
    # 排除匹配:不在exclude列表中
    exclude_mask = ~filtered_a['CONSTRUCTION_TYPE_FAMILY'].isin(family_exclude)
    
    final_filtered = filtered_a[include_mask & exclude_mask]
    if final_filtered.empty:
        return pd.Series([None, None])
    
    # 返回第一个匹配结果的步骤数(需求不同可改成取均值/全部结果)
    return pd.Series([final_filtered.iloc[0]['翻新步骤数'], final_filtered.iloc[0]['预防性维护步骤数']])

步骤3:批量应用到DataFrame B

假设你的两个数据集分别为df_a和df_b,执行以下代码完成匹配:

# 给df_b新增匹配到的步骤数字段
df_b[['翻新步骤数', '预防性维护步骤数']] = df_b.apply(lambda x: match_equipment(x, df_a), axis=1)

补充说明

  • 如果CONSTRUCTOR需要模糊匹配,将第一步的==替换为str.contains(..., na=False)
  • 模糊匹配规则可根据实际样本调整(比如H3xx如果限定为H3+两位数字,正则改成H3\d{2})
  • 若存在多个匹配结果,可修改返回逻辑(比如取所有结果的平均值,或用explode保留全部匹配项)

内容的提问来源于stack exchange,提问作者Taylor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 09:13:18