如何将事件型Pandas DataFrame转换为方波时间序列?
将事件型DataFrame转换为时间序列DataFrame
核心思路
我们需要把每个事件的起止时间点、以及事件结束后的第一个时间点都纳入时间序列,同时给对应区间赋值:事件持续区间内用原value,区间外(包括事件结束后的时间)赋值0。
下面提供两种实用的实现方法,根据你的数据规模选择即可:
方法一:高效匹配(适合大跨度/少事件场景)
这种方法不需要生成所有中间时间点,通过关键时间点匹配来赋值,内存占用更低:
import pandas as pd # 示例原数据 data = { 'start_time': [1671221209, 1671240425, 1671289246], 'end_time': [1671234984, 1671241235, 1671289600], 'value': [2000, 1000, 133] } df = pd.DataFrame(data) # 1. 提取所有关键时间点:事件开始、事件结束、结束后第一个时间点 time_points = [] for _, row in df.iterrows(): time_points.extend([row['start_time'], row['end_time'], row['end_time'] + 1]) # 去重并排序得到完整时间序列框架 time_points = sorted(set(time_points)) time_df = pd.DataFrame({'time': time_points}) # 2. 给每个时间点匹配对应的value # 先给原数据标记事件结束的下一个时间点 df['end_next'] = df['end_time'] + 1 # 用merge_asof匹配最近的事件起始时间 time_df = pd.merge_asof(time_df.sort_values('time'), df[['start_time', 'end_next', 'value']].sort_values('start_time'), left_on='time', right_on='start_time', direction='backward') # 3. 修正区间外的value为0 time_df['value'] = time_df.apply(lambda x: x['value'] if x['time'] < x['end_next'] else 0, axis=1) # 清理结果 result = time_df[['time', 'value']].sort_values('time').reset_index(drop=True) print(result)
方法二:直接生成全量时间点(适合短区间/多事件场景)
这种方法逻辑更直观,直接生成每个事件的所有时间点,再补全空白区间:
import pandas as pd # 示例原数据 data = { 'start_time': [1671221209, 1671240425, 1671289246], 'end_time': [1671234984, 1671241235, 1671289600], 'value': [2000, 1000, 133] } df = pd.DataFrame(data) # 1. 生成每个事件对应的时间序列DataFrame event_dfs = [] for _, row in df.iterrows(): # 生成从start到end的所有秒级时间点(转换为时间戳整数) time_range = pd.date_range(start=pd.to_datetime(row['start_time'], unit='s'), end=pd.to_datetime(row['end_time'], unit='s'), freq='s').astype(int) // 10**9 event_df = pd.DataFrame({'time': time_range, 'value': row['value']}) event_dfs.append(event_df) # 2. 合并所有事件数据 combined = pd.concat(event_dfs) # 3. 生成完整的时间跨度:从最早事件开始到最晚事件结束后1秒 min_time = df['start_time'].min() max_time = df['end_time'].max() + 1 full_time_range = pd.Series(range(min_time, max_time + 1)) # 4. 补全空白时间点,未覆盖的区间赋值0 result = combined.set_index('time').reindex(full_time_range, fill_value=0).reset_index().rename(columns={'index': 'time'}) print(result)
内容的提问来源于stack exchange,提问作者Lênis Parge
相关产品推荐
相关产品推荐

