You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取DataFrame中指定时间点后首次出现的新事件?

问题:获取个体时间序列中的首次新事件

原始数据

idtime1time2time3event1event2event3
a2011-04-22[]2016-06-07[apple, orange][][orange, grape]
b2010-07-152014-07-122015-05-10[apple][apple, orange][apple, orange, grape]

需求说明

需要获取指定初始时间点(如time1)之后,每个后续时间点出现的首次新事件(即该事件未在之前所有时间点出现过),但当某时间列为空(无事件)时,原代码无法正确计算。

初始错误代码

def substracttest(i):
    if (i>2):
        df['new_event'+str(i)]=df['event'+str(i)].apply(lambda x: [k for k in x if k not in substracttest(i-1)]).values
        return(df['new_event'+str(i)])
    else:
        df['new_event'+str(i)]=df['event'+str(i)].apply(lambda x: [k for k in x if k not in df['event'+str(i-1)]]).values
        return(df['new_event'+str(i)])


for j in range(2,4):
    substracttest(j)

错误输出

new_event1         new_event2
[]                 [orange, grape]
[apple, orange]    [apple, orange, grape]

期望输出

new_event1  new_event2
[]          [grape]
[orange]    [grape]

调整后可行代码

import numpy as np

def substracttest(i):
    if (i>2):
        df['new_event'+str(i)]=df.apply(lambda row : np.setdiff1d(row['event'+str(i)],row['new_event'+str(i-1)]), axis=1)
        for j in range(1,i):
            df['new_event'+str(i)]=df.apply(lambda row : np.setdiff1d(row['new_event'+str(i)],row['event'+str(j)]), axis=1)
        return(df)
    else:
        df['new_event'+str(i)]=df.apply(lambda row : np.setdiff1d(row['event'+str(i)],row['event'+str(i-1)]), axis=1)
        return(df)


for j in range(2,4):
    substracttest(j)

其他可行实现思路

思路1:长表格式转换后处理

先将宽表转为长表(每个id-时间点为一行),过滤无事件行后按时间排序,通过累积事件集合计算新事件,更适配时间点数量不固定的场景:

import pandas as pd

# 转换为长表格式
long_df = df.melt(id_vars=['id'], 
                  value_vars=[f'time{k}' for k in range(1,4)] + [f'event{k}' for k in range(1,4)],
                  var_name='type', 
                  value_name='value')

# 拆分时间点序号和类型(时间/事件)
long_df['time_point'] = long_df['type'].str.extract('(\d+)')
long_df['type'] = long_df['type'].str.replace('\d+', '')

# 透视回宽表,按id和时间点分组
long_df = long_df.pivot(index=['id', 'time_point'], columns='type', values='value').reset_index()

# 过滤无事件的行
long_df = long_df[long_df['event'].apply(lambda x: len(x) > 0)]

# 按id和时间排序
long_df['time'] = pd.to_datetime(long_df['time'])
long_df = long_df.sort_values(['id', 'time'])

# 分组累积事件集合,计算新事件
def calculate_new_events(group):
    seen = set()
    new_events = []
    for events in group['event']:
        new = [e for e in events if e not in seen]
        new_events.append(new)
        seen.update(events)
    group['new_event'] = new_events
    return group

result = long_df.groupby('id').apply(calculate_new_events)

思路2:逐行遍历累积事件集合

直接对每行数据按时间顺序遍历事件列,维护已出现事件的集合,逻辑简单易理解:

# 定义时间列和事件列的范围
time_cols = [f'time{k}' for k in range(1,4)]
event_cols = [f'event{k}' for k in range(1,4)]

# 逐行处理每个个体的事件序列
for idx, row in df.iterrows():
    seen = set()
    # 先加入初始时间点的所有事件
    seen.update(row[event_cols[0]])
    # 遍历后续每个时间点
    for i in range(1, len(event_cols)):
        current_events = row[event_cols[i]]
        # 筛选出未出现过的新事件
        new_events = [e for e in current_events if e not in seen]
        df.loc[idx, f'new_event{i}'] = new_events
        # 更新已出现事件集合
        seen.update(current_events)

内容的提问来源于stack exchange,提问作者Anakorang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 22:24:59