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

如何在Pandas中按复合逻辑条件分组并获取分组集合?

实现基于复合逻辑的Pandas分组(连通分量优化版)

核心思路

你的需求本质是按复合逻辑定义的等价关系分组:满足逻辑条件的行属于同一连通组。这类问题绕不开连通分量计算,但可以用更简洁的工具链实现,同时适配通用复合逻辑场景。

步骤1:拆分复合逻辑

先把复合逻辑拆成两层:

  • 外层「与」条件:必须完全匹配的列(比如Col1,或者Col1+Col2)
  • 内层「或」子句:每个子句中至少有一列匹配即可,多个子句需同时满足

步骤2:用NetworkX简化连通分量计算

不用手动实现图结构,直接借助networkx的connected_components方法,结合Pandas分组操作,代码更简洁易维护:

示例代码(适配Col1 and (Col2 or Col3))

import pandas as pd
import networkx as nx

# 加载示例数据
df = pd.DataFrame({
    'Name': ['John', 'Sam', 'Mike', 'Kate', 'Fred', 'Liz', 'Jane', 'Henry'],
    'Col1': [1,1,1,2,3,3,4,4],
    'Col2': ['A','B','B','E','E','F','X','Z'],
    'Col3': ['C','C','D','G','H','H','Y','T']
})

def group_by_complex_logic(df, group_cols, connect_clauses):
    """
    :param df: 输入DataFrame
    :param group_cols: 外层「与」条件的列列表(如['Col1'])
    :param connect_clauses: 内层「或」子句列表,每个子句是列列表(如[['Col2'], ['Col3']],表示Col2相同或Col3相同)
    """
    result = []
    # 先按外层「与」条件拆分大组
    for _, sub_df in df.groupby(group_cols):
        G = nx.Graph()
        G.add_nodes_from(sub_df['Name'])
        # 按「或」子句给匹配的节点连边
        for clause in connect_clauses:
            # 同一子句内列值相同的节点互相连边
            for _, match_group in sub_df.groupby(clause):
                names = match_group['Name'].tolist()
                # 给同组节点添加全连接边
                for i in range(len(names)):
                    for j in range(i+1, len(names)):
                        G.add_edge(names[i], names[j])
        # 提取连通分量并加入结果
        components = [list(comp) for comp in nx.connected_components(G)]
        result.extend(components)
    return result

# 调用示例
output = group_by_complex_logic(df, ['Col1'], [['Col2'], ['Col3']])
print(output)

输出结果

[['John', 'Sam', 'Mike'], ['Kate'], ['Fred', 'Liz'], ['Jane'], ['Henry']]

适配通用复合逻辑(如Col1 and Col2 and (Col3 or Col4) and (Col5 or Col6))

如果逻辑要求多个「或」子句同时满足,只需调整连边的判断逻辑:

def group_by_complex_logic_v2(df, group_cols, connect_clauses):
    """
    适配多子句同时满足的场景:外层「与」分组后,节点间连边需满足所有「或」子句
    :param connect_clauses: 如[[['Col3','Col4'], ['Col5','Col6']]],表示(Col3相同或Col4相同) 且 (Col5相同或Col6相同)
    """
    result = []
    for _, sub_df in df.groupby(group_cols):
        G = nx.Graph()
        G.add_nodes_from(sub_df['Name'])
        names = sub_df['Name'].tolist()
        # 遍历所有节点对,判断是否满足所有子句条件
        for i in range(len(names)):
            row_a = sub_df[sub_df['Name'] == names[i]].iloc[0]
            for j in range(i+1, len(names)):
                row_b = sub_df[sub_df['Name'] == names[j]].iloc[0]
                # 检查所有子句是否至少有一列匹配
                all_satisfied = True
                for clause in connect_clauses:
                    clause_ok = any(row_a[col] == row_b[col] for col in clause)
                    if not clause_ok:
                        all_satisfied = False
                        break
                if all_satisfied:
                    G.add_edge(names[i], names[j])
        components = [list(comp) for comp in nx.connected_components(G)]
        result.extend(components)
    return result

优势说明

  • 复用成熟的连通分量算法,避免手动实现Union-Find的繁琐
  • 代码模块化,仅需调整group_cols和connect_clauses即可适配不同逻辑
  • 兼顾可读性与扩展性,日常数据处理场景下效率足够

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 11:18:13