基于Pandas多时间列计算候诊室小时级负载的实现问题
候诊室周维度每小时负载实现方案
核心实现逻辑
我们可以通过展开每位访客在店期间覆盖的所有整点时段,再按星期几+小时维度聚合统计的方式实现需求,完全匹配你给出的计算规则。
完整代码(基于你提供的MWE修改)
from datetime import timedelta import numpy as np import pandas as pd # 你原有的随机数据生成逻辑 startday= pd.to_datetime("1/1/2021") endday = pd.to_datetime("1/14/2021") arrival= pd.DatetimeIndex( (10**9*np.random.randint(startday.value//10**9, endday.value//10**9, 2000)) ).sort_values() treatment = pd.DatetimeIndex( [s + timedelta(minutes=np.random.randint(5, 55)) for s in arrival] ) finish = pd.DatetimeIndex( [s + timedelta(minutes=np.random.randint(15, 60)) for s in treatment] ) waiting = treatment - arrival df = pd.DataFrame( data={ "arrival": arrival, "treatment": treatment, "finish": finish, "waiting": waiting, }, index=arrival, ) # ----------------- 新增负载计算逻辑 ----------------- # 1. 为每条访客记录生成其在店期间覆盖的所有整点时段 df['covered_hours'] = df.apply( lambda row: pd.date_range( start=row['arrival'].floor('H'), end=row['finish'].floor('H'), freq='H' ), axis=1 ) # 2. 展开时段,每条记录对应一个小时 df_hourly = df.explode('covered_hours', ignore_index=True) # 3. 提取时段的星期几、小时属性 df_hourly['weekday'] = df_hourly['covered_hours'].dt.weekday df_hourly['hour'] = df_hourly['covered_hours'].dt.hour # 4. 按星期几+小时聚合统计负载 load_stats = df_hourly.groupby(['weekday', 'hour']).size().rename('load') # ----------------- 合并到你原有df2结构 ----------------- df2 = pd.DataFrame( data={ "arrival": df["arrival"] .groupby([(idx := df["arrival"].dt).weekday, idx.hour]) .count(), "treatment": df["treatment"] .groupby([(idx := df["treatment"].dt).weekday, idx.hour]) .count(), "finish": df["finish"] .groupby([(idx := df["finish"].dt).weekday, idx.hour]) .count(), }, ).fillna(0) df2["waiting"] = ( df["waiting"].groupby([(idx := df["arrival"].dt).weekday, idx.hour]).mean() ) # 合并负载数据 df2 = df2.join(load_stats, how='left').fillna({'load': 0}) # 如果需要计算每周同时段的平均负载,可以除以总周数 total_period_weeks = (endday - startday).days // 7 + 1 df2['avg_load_per_week'] = df2['load'] / total_period_weeks
逻辑验证
针对你给出的简单示例,上述逻辑的计算结果完全匹配:
示例输入:
arrival = [10:00, 10:15, 10:45, 11:30, 11:45, 12:15] finish = [10:30, 10:59, 11:45, 12:30, 12:45, 13:00]
计算得到的各时段负载:
- 10点:3人,匹配
3+0 - 11点:3人,匹配
2+1 - 12点:3人,匹配
1+2
扩展说明
如果需要更换统计时间间隔(比如改为每15分钟统计),只需要修改pd.date_range里的freq参数,以及提取时间属性的逻辑即可,整体框架不需要调整。
内容的提问来源于stack exchange,提问作者Paw
相关产品推荐
相关产品推荐

