
本文介绍如何在 Pandas 中基于多条件过滤(如 colC > 0 且 colB 属于指定集合),按 colA 分组统计 colB 的唯一值个数,并仅保留计数大于 2 的分组,最终导出对应原始数据子集。
本文介绍如何在 pandas 中基于多条件过滤(如 `colc > 0` 且 `colb` 属于指定集合),按 `cola` 分组统计 `colb` 的唯一值个数,并仅保留计数大于 2 的分组,最终导出对应原始数据子集。
在数据分析中,常需对满足复合业务逻辑的子集进行分组聚合与二次筛选。本例典型场景是:仅关注那些在关键指标列(colC > 0)和白名单维度(colB ∈ key_id)双重约束下,仍拥有至少 3 个不同 colB 值的 colA 组,并进一步提取这些组的全部原始记录用于下游处理(如导出 CSV)。
✅ 核心步骤分解
- 前置过滤:先用布尔索引筛选出 colC > 0 且 colB 在 key_id 集合中的行;
- 分组聚合:按 colA 分组,使用 .agg(UniqueNum='nunique') 统计每组中 colB 的去重数量;
- 后置筛选:对聚合结果应用条件过滤(UniqueNum > 2),保留符合条件的 colA;
- 反向提取原始数据:利用筛选出的 colA 值,从原始数据中定位所有匹配行,完成最终子集构建。
? 示例代码实现
import pandas as pd
# 示例数据(请替换为实际 filtData)
data = {
'colA': [1105904, 1105904, 1105904, 1105904, 1105904,
1105905, 1105905, 1105905, 1105905, 1105905, 1105905,
1111111, 1111111, 1111111, 1111111, 1111111],
'colB': [1007, 1008, 2000, 1004, 1005,
1008, 1001, 1004, 1005, 1072, 1093,
1001, 1002, 1003, 1004, 1093],
'colC': [867.0, 93.33, 0.42, 0.0, 4.0,
4.0, 0.0, 0.0, 1.5, 4.0, 0.25,
0.35, 0.10, 0.0, 0.25, 0.25]
}
filtData = pd.DataFrame(data)
# 定义白名单集合
key_id = {1008, 1051, 1003, 1005, 1072, 1079, 1092, 1093, 1004, 2000}
# 步骤1 & 2 & 3:过滤 → 分组 → 聚合 → 筛选
valid_colA = (
filtData.loc[(filtData['colC'] > 0) & (filtData['colB'].isin(key_id)), 'colB']
.groupby(filtData['colA'])
.agg(UniqueNum='nunique')
.reset_index()
.query('UniqueNum > 2')['colA'] # 提取满足条件的 colA 值
)
# 步骤4:反向获取完整原始记录子集
filtered_df = filtData[filtData['colA'].isin(valid_colA)].copy()
# 可选:导出为 CSV
# filtered_df.to_csv('filtered_output.csv', index=False)
print("✅ 满足条件的 colA 分组及唯一 colB 数量:")
print(
filtData.loc[(filtData['colC'] > 0) & (filtData['colB'].isin(key_id)), 'colB']
.groupby(filtData['colA'])
.agg(UniqueNum='nunique')
.reset_index()
.query('UniqueNum > 2')
)
print("\n? 最终筛选出的原始数据子集:")
print(filtered_df)⚠️ 注意事项与最佳实践
- 链式操作稳定性:.query() 和 .loc[lambda x: ...] 均可安全用于聚合后筛选,推荐 .query() —— 语法简洁、可读性强,且自动处理列名引用;
- 避免重复计算:不要在 .loc 过滤前就调用 .groupby(...).nunique(),否则会统计全量 colB(含 colC ≤ 0 或 colB ∉ key_id 的无效项);
- 空结果防护:若无分组满足 UniqueNum > 2,valid_colA 将为空 Series,isin() 会自然返回空 DataFrame,无需额外判空;
- 性能优化提示:当数据量极大时,可先用 filtData = filtData.query('colC > 0').copy() 预过滤,再执行 isin(key_id),减少布尔运算开销。
通过以上方法,你不仅能精准获得目标分组摘要,还能无缝衔接至原始数据提取环节,为后续分析或导出奠定坚实基础。

















