如何在pandas中基于其他行的数值筛选符合指定条件的行元组
pandas实现方案
该需求可以通过pandas实现,核心是通过自连接匹配符合条件的行对,再用连通性聚合得到最终组,完整实现步骤如下:
1. 构造示例数据
import pandas as pd df = pd.DataFrame({ 'A': [1, 10, 7, 0, 9, 7], 'B': [2, 9, 4, 3, 10, 10] }) # 给每行添加唯一标识用于后续关联 df['row_id'] = range(len(df))
2. 筛选符合条件的行对
通过全量自连接得到所有行的两两组合,再按规则过滤:
# 自连接生成所有行对 cross_df = df.merge(df, how='cross', suffixes=('_current', '_other')) # 过滤规则:其他行B>当前行B,且其他行A<当前行A,且不是同一行 valid_pairs = cross_df[ (cross_df['B_other'] > cross_df['B_current']) & (cross_df['A_other'] < cross_df['A_current']) & (cross_df['row_id_current'] != cross_df['row_id_other']) ]
3. 关联行聚合为组
用并查集算法把有连通关系的行合并到同一组,得到最终结果:
# 简单并查集实现 class UnionFind: def __init__(self, size): self.parent = list(range(size)) def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): fx, fy = self.find(x), self.find(y) if fx != fy: self.parent[fy] = fx uf = UnionFind(len(df)) # 合并有匹配关系的行ID for _, row in valid_pairs.iterrows(): uf.union(int(row['row_id_current']), int(row['row_id_other'])) # 按组聚合输出结果 df['group_id'] = [uf.find(i) for i in range(len(df))] result = [] for _, group in df.groupby('group_id'): if len(group) > 1: # 过滤无匹配的孤立行 res_tuple = tuple(group[['A','B']].itertuples(index=False, name=None)) result.append(res_tuple)
运行后输出的result值为:
[((1, 2), (0, 3)), ((10, 9), (9, 10), (7, 10))]
和预期结果完全一致。
补充说明:如果数据量较大(超过10万行),全量笛卡尔积的O(n²)复杂度会比较高,可以先按B列升序排序,再逐行匹配后续行的A列值,能大幅降低计算耗时。
内容的提问来源于stack exchange,提问作者CopperKettle
相关产品推荐
相关产品推荐

