请求:基于日期与时间窗口重塑Pandas DataFrame并标记时段
实现方法
先明确示例数据
假设你的原始DataFrame如下:
import pandas as pd df = pd.DataFrame({ 'id': ['A', 'A', 'B'], 'date': ['2024-01-01', '2024-01-02', '2024-01-01'], 'time_start': ['09:00', '14:15', '10:30'], 'end_start': ['09:45', '15:00', '11:00'] })
目标是生成包含所有id-date组合、每个15分钟时段标记0/1的宽表。
步骤1:生成全量15分钟时段列表
先创建一天内所有15分钟间隔的时间字符串,作为最终表的列名:
# 生成00:00到23:45的15分钟间隔时段 time_slots = pd.date_range('00:00', '23:45', freq='15min').strftime('%H:%M').tolist()
步骤2:构建id与date的全量组合
确保每个id的每个日期都有记录,哪怕原始数据中没有对应条目:
# 获取唯一id和日期集合 unique_ids = df['id'].unique() unique_dates = df['date'].unique() # 生成id和date的笛卡尔积 full_index = pd.MultiIndex.from_product([unique_ids, unique_dates], names=['id', 'date']) full_df = pd.DataFrame(index=full_index).reset_index()
步骤3:标记原始数据覆盖的时段
转换时间列类型,然后计算每条记录覆盖的15分钟时段:
# 将时间字符串转为datetime.time类型 df['time_start'] = pd.to_datetime(df['time_start']).dt.time df['end_start'] = pd.to_datetime(df['end_start']).dt.time # 定义函数:判断单个记录覆盖的时段 def mark_covered_slots(row): start = row['time_start'] end = row['end_start'] # 生成所有15分钟时间点的time类型集合 all_slots_time = pd.date_range('00:00', '23:45', freq='15min').time # 标记每个时段是否在[start, end]区间内 return pd.Series([1 if start <= slot <= end else 0 for slot in all_slots_time], index=time_slots) # 应用函数获取每条记录的时段标记 slot_marks = df.apply(mark_covered_slots, axis=1) # 合并id、date与标记结果 df_marked = pd.concat([df[['id', 'date']], slot_marks], axis=1)
步骤4:合并全量框架并填充0
将全量id-date组合与标记数据合并,缺失的时段自动填充0:
# 左连接合并,确保所有id-date组合都保留 result = full_df.merge(df_marked, on=['id', 'date'], how='left').fillna(0) # 将标记列转为整数类型 result[time_slots] = result[time_slots].astype(int)
最终的result就是你需要的目标DataFrame。
补充调整
如果你的end_start是时段结束点(不包含该时段),可以把判断条件改为start <= slot < end;如果date列是datetime类型,需先统一格式确保匹配。
内容的提问来源于stack exchange,提问作者Sadcow
相关产品推荐
相关产品推荐

