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

请求:基于日期与时间窗口重塑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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 18:42:51