如何结合Pandas GroupBy与Drop筛选符合指定递增序列的分组数据
Pandas按分组筛选包含指定单调递增序列的行
我来帮你搞定这个分组筛选的问题!先看你给出的示例数据:
import pandas as pd df = pd.DataFrame({ 'UNIT': ['a100', 'a100', 'a100', 'a100', 'b222', 'b222', 'b222', 'b222'], 'MACHINE': ['001', '002', '003', '001', '001', '002', '002', '003'] })
你的需求很明确:按UNIT列分组,只要某个分组的MACHINE序列完整包含任意一个指定的单调递增序列(哪怕中间夹着重复值),就保留这个分组的所有行;如果完全不符合(比如a100的序列最后回退到001,没完整匹配目标序列)就剔除整个分组。
解决方案思路
核心是用groupby.filter()方法,配合一个自定义检查函数——这个函数会判断当前分组的MACHINE序列是否包含我们指定的任意一个目标单调递增子序列。
步骤1:定义目标序列和检查函数
首先把所有需要匹配的单调递增序列存成列表,比如:
# 可以添加多个目标单调递增序列 target_sequences = [ ['001', '002', '003'], ['002', '003', '004'] # 示例第二个目标序列 ]
然后写一个辅助函数,用来检查单个分组是否符合要求:
def has_target_sequence(group, targets): machine_list = group['MACHINE'].tolist() # 遍历每个目标序列,只要有一个匹配就返回True for target in targets: ptr = 0 # 目标序列的遍历指针 for item in machine_list: if ptr < len(target) and item == target[ptr]: ptr += 1 # 如果指针走到目标序列末尾,说明完整匹配了这个子序列 if ptr == len(target): return True # 所有目标序列都不匹配,返回False return False
这个函数的逻辑很直观:对每个目标单调递增序列,我们按顺序在分组的MACHINE列表里找对应的元素,只要能按顺序把目标序列的所有元素都找到(不管中间有多少重复或无关值),就判定这个分组符合要求。
步骤2:用groupby.filter筛选分组
直接调用filter方法就能筛选出符合条件的分组:
filtered_df = df.groupby('UNIT').filter(lambda x: has_target_sequence(x, target_sequences))
运行后得到的filtered_df就是你想要的结果:
UNIT MACHINE 4 b222 001 5 b222 002 6 b222 002 7 b222 003
为什么用filter而不是drop?
groupby.filter()会直接保留整个符合条件的分组,不需要手动计算要删除的行索引,逻辑更清晰,代码也更简洁,比先找索引再drop高效得多。
内容的提问来源于stack exchange,提问作者sepideh
相关产品推荐
相关产品推荐

