按ID分组筛选面板数据中start=1后首个满足条件的时间
按ID分组查找面板数据中首个符合条件的时间点
问题描述
给定包含id、time的面板数据,需按id分组,在每组start=1的记录之后,找到首个满足**当前行的number in大于start=1之后、当前行之前任意一条记录的number out**的time。
示例逻辑:
- id=1:
start=1出现在time=1,从time=2开始追踪,time=5的number in=4大于start后time=3的number out=1,因此对应time=5 - id=2:
start=1出现在time=1,time=3的number in=7大于start后time=2的number out=2,因此对应time=3
示例数据
import pandas as pd df = pd.DataFrame({ 'id': [1, 1, 1, 1, 1, 2, 2, 2, 2], 'time': [1, 2, 3, 4, 5, 1, 2, 3, 4], 'start': [1, 0, 0, 0, 0, 1, 0, 0, 0], 'number out': [2, 99, 1, 13, 9, 10, 2, 8, 8], 'number in': [2, 9, 1, 0, 4, 1, 5, 7, 8] }) print(df)
示例输出
id time start number out number in 0 1 1 1 2 2 1 1 2 0 99 9 2 1 3 0 1 1 3 1 4 0 13 0 4 1 5 0 9 4 5 2 1 1 10 1 6 2 2 0 2 5 7 2 3 0 8 7 8 2 4 0 8 8
解决方案
实现代码
def find_first_matching_time(group): # 定位当前组中start=1的行 start_row = group[group['start'] == 1] if start_row.empty: return None start_idx = start_row.index[0] # 取start行之后的所有记录 post_start_records = group.loc[start_idx + 1:] if post_start_records.empty: return None # 滚动计算到当前行之前的number out最小值(只要大于最小值,就满足大于至少一个历史值) rolling_min_out = post_start_records['number out'].shift(1).expanding().min() # 筛选符合条件的行:number in > 历史number out最小值 valid_records = post_start_records[post_start_records['number in'] > rolling_min_out.fillna(False)] return valid_records.iloc[0]['time'] if not valid_records.empty else None # 按id分组执行逻辑,得到结果 result = df.groupby('id').apply(find_first_matching_time).reset_index(name='first_matching_time') print(result)
代码说明
- 分组定位起始点:对每个
id组,先找到start=1的行,确定后续处理的起始位置 - 滚动计算历史最小值:对
start之后的行,用滚动窗口计算当前行之前所有number out的最小值——只要当前number in大于这个最小值,就说明它大于之前出现过的至少一个number out - 筛选首个符合条件的记录:从符合条件的记录中取第一条,返回其
time值
运行结果
id first_matching_time 0 1 5 1 2 3
内容的提问来源于stack exchange,提问作者HnV
相关产品推荐
相关产品推荐

