如何用Pythonic方式高效过滤Pandas DataFrame?
高效拆分Pandas DataFrame的Pythonic方案
针对大数据量的Pandas DataFrame拆分需求,完全不需要用循环处理,利用Pandas的分组聚合+向量化操作就能实现高效处理,以下是具体实现方案:
核心思路
先按时间列c1分组,识别每个时间点包含的探测器类型集合(或用位运算编码),再根据类型组合的条件筛选出对应DataFrame,全程避免逐行循环,充分利用Pandas的内部优化机制。
方案一:集合判断法(直观易读)
先构造示例数据,再执行拆分:
import pandas as pd # 构造示例数据(模拟用户提供的结构) data = { 'c1': [1,1,2,2,2,3,3,4,4], 'c2': [1,2,1,2,3,2,3,1,3], 'c3': [10,20,15,25,35,22,32,17,37] } df = pd.DataFrame(data) # 按c1分组,获取每个时间点的探测器类型集合 detector_sets = df.groupby('c1')['c2'].agg(set).rename('detector_set') # 将集合信息合并回原DataFrame df_with_set = df.merge(detector_sets, on='c1') # 按需求拆分出4个DataFrame # 1. 包含所有c1下存在1和2类型的行 df_12 = df_with_set[df_with_set['detector_set'].apply(lambda x: {1,2}.issubset(x))] # 2. 包含所有c1下存在1和3类型的行 df_13 = df_with_set[df_with_set['detector_set'].apply(lambda x: {1,3}.issubset(x))] # 3. 包含所有c1下存在2和3类型的行 df_23 = df_with_set[df_with_set['detector_set'].apply(lambda x: {2,3}.issubset(x))] # 4. 包含所有c1下同时存在1、2、3类型的行 df_123 = df_with_set[df_with_set['detector_set'].apply(lambda x: {1,2,3}.issubset(x))]
方案二:位运算编码法(性能更优)
对于超大数据集,用位运算替代集合判断能进一步提升效率:
import pandas as pd # 构造示例数据 data = { 'c1': [1,1,2,2,2,3,3,4,4], 'c2': [1,2,1,2,3,2,3,1,3], 'c3': [10,20,15,25,35,22,32,17,37] } df = pd.DataFrame(data) # 将探测器类型转为二进制位编码:1→1(0b001)、2→2(0b010)、3→4(0b100) df['c2_bit'] = df['c2'].map({1: 1, 2: 2, 3: 4}) # 按c1分组,计算每个时间点的位掩码(所有类型的位或结果) bit_masks = df.groupby('c1')['c2_bit'].agg(lambda x: x.unique().sum()).rename('bit_mask') df_with_mask = df.merge(bit_masks, on='c1') # 用位运算快速筛选 df_12 = df_with_mask[(df_with_mask['bit_mask'] & 3) == 3] # 3=1|2,同时包含1和2 df_13 = df_with_mask[(df_with_mask['bit_mask'] & 5) == 5] # 5=1|4,同时包含1和3 df_23 = df_with_mask[(df_with_mask['bit_mask'] & 6) == 6] # 6=2|4,同时包含2和3 df_123 = df_with_mask[(df_with_mask['bit_mask'] & 7) == 7] #7=1|2|4,包含全部三种类型
效率说明
这两种方案都避免了手动循环,依赖Pandas的C优化底层实现,处理百万级以上数据时,效率比逐行循环高几十甚至上百倍。如果需要排除“同时包含三种类型”的行(即仅保留两种类型的组),只需在筛选条件中增加len(x)==2(方案一)或bit_mask !=7(方案二)即可。
内容的提问来源于stack exchange,提问作者Euler
相关产品推荐
相关产品推荐

