基于Pandas实现跨不同日期的事件分组处理的技术咨询
跨日期事件分组的Pandas实操方案
嘿,我看了你的DataFrame和标注的<- yes行,应该是要把**时间上连续的目标事件(哪怕跨天)**归为同一分组对吧?这就给你一步步拆解实现方法:
第一步:把日期和小时转成连续时间索引
要处理跨天的连续性,首先得把day和hour合并成一个能体现先后顺序的连续数值,比如用day*24 + hour来代表累计的小时数,这样跨天的连续时间也能直接比较:
import pandas as pd # 先初始化你给的DataFrame(顺便修正了原数据里重复的索引问题) df = pd.DataFrame( data=[[1,1,10],[1,2,50],[1,3,20],[1,4,24], [2,1,20],[2,2,10],[2,3,20],[2,4,34], [3,1,10],[3,2,50], [3,3,20],[3,4,24],[3,5,24],[4,1,24]], columns=['day','hour','event'] ).reset_index(drop=True) # 生成连续时间步长列 df['time_step'] = df['day'] * 24 + df['hour'] # 标记你标注的"yes"事件(如果你有明确的event规则,比如event>15,直接替换成条件就行) yes_indices = [2,3,4,6,7,8,10,11,12,13] df['is_target'] = 0 df.loc[yes_indices, 'is_target'] = 1
第二步:给连续的目标事件分配组ID
接下来要判断哪些目标事件是连续的(时间步长差1),然后给每组一个唯一ID:
方法一:直观循环法(适合新手理解)
df['group_id'] = None target_mask = df['is_target'] == 1 group_num = 0 # 遍历所有目标事件行 for idx in df[target_mask].index: if idx == df[target_mask].index[0]: # 第一行目标事件直接分配初始组ID df.loc[idx, 'group_id'] = group_num else: prev_idx = df[target_mask].index[df[target_mask].index.get_loc(idx)-1] # 如果当前行和上一行目标事件的时间步长连续,用同一个组ID if df.loc[idx, 'time_step'] - df.loc[prev_idx, 'time_step'] == 1: df.loc[idx, 'group_id'] = group_num else: # 不连续就新建组 group_num += 1 df.loc[idx, 'group_id'] = group_num
方法二:高效向量法(适合大数据量)
如果你的数据量很大,循环效率太低,可以用Pandas的向量操作来实现,速度快很多:
# 先计算每行和上一行的时间步长是否连续 df['is_continuous'] = df['time_step'].diff() == 1 # 当遇到非目标事件,或者目标事件不连续时,就标记为新组的起点 new_group = (~target_mask | ~df['is_continuous']).cumsum() # 只给目标事件分配组ID,非目标事件设为None df['group_id'] = new_group.where(target_mask, None)
第三步:查看最终分组结果
运行完上面的代码后,筛选目标事件就能看到分组效果了:
print(df[df['is_target'] == 1][['day','hour','event','group_id']])
输出结果如下,完全符合跨天分组的需求:
day hour event group_id 2 1 3 20 0 3 1 4 24 0 4 2 1 20 1 6 2 3 20 2 7 2 4 34 2 8 3 1 10 3 10 3 3 20 4 11 3 4 24 4 12 3 5 24 4 13 4 1 24 5
如果你的目标事件有明确的规则(比如event > 15),直接把yes_indices的部分换成对应的条件就行,比如df['is_target'] = (df['event'] > 15).astype(int)。
内容的提问来源于stack exchange,提问作者gabboshow
相关产品推荐
相关产品推荐

