非唯一Plan_Start索引下日期天数统计报错及解决方案问询
处理重复Plan_Start日期的患者治疗计划每日序列生成问题
当患者同一天启动多个治疗计划(含当天结束的短周期计划)时,原基于resample的方法会因非唯一索引报错。以下是替代方案,可保留所有计划的完整时间序列,同时正确处理重叠/重复日期场景:
解决方案代码
import pandas as pd # 初始化并处理日期格式 tx2 = pd.DataFrame({ 'Patient':[123,456,789,789,789,101], 'Plan':['Drug1','Drug43','Drug_abc','Drug_xyz','Drug_123','Drug_324'], 'Plan_Start':['4/21/2021','6/11/2021','7/7/2021','7/7/2021','7/17/2021','9/20/2021'], 'Plan_End':['1/1/2030','7/20/2021','7/7/2022','7/17/2021','07/31/2021','9/20/2022'] }) tx2['Plan_Start'] = pd.to_datetime(tx2['Plan_Start']) tx2['Plan_End'] = pd.to_datetime(tx2['Plan_End']) # 逐患者生成每日序列 result_list = [] for patient, group in tx2.groupby('Patient'): # 获取该患者所有唯一的治疗起始日期并排序 unique_starts = sorted(group['Plan_Start'].unique()) for _, plan_row in group.iterrows(): start_date = plan_row['Plan_Start'] # 找到当前起始日期在唯一列表中的位置 start_idx = unique_starts.index(start_date) # 计算计划的实际结束日期:取自身结束日和下一个计划起始日的前一天的较小值 if start_idx < len(unique_starts) - 1: next_plan_start = unique_starts[start_idx + 1] actual_end = min(plan_row['Plan_End'], next_plan_start - pd.Timedelta(days=1)) else: # 无后续计划,直接用原计划结束日 actual_end = plan_row['Plan_End'] # 生成该计划的每日日期序列 daily_dates = pd.date_range(start=start_date, end=actual_end, freq='D') daily_df = pd.DataFrame({ 'Date': daily_dates, 'Patient': patient, 'Plan': plan_row['Plan'], 'Original_Plan_Start': start_date, 'Original_Plan_End': plan_row['Plan_End'] }) result_list.append(daily_df) # 合并所有患者的结果 final_result = pd.concat(result_list, ignore_index=True)
方案说明
- 日期预处理:统一转换
Plan_Start和Plan_End为datetime类型,确保时间计算准确。 - 分组处理:按患者分组,避免跨患者的计划干扰。
- 唯一起始日期校准:提取每个患者的唯一治疗起始点,确保后续时间分段不重复。
- 动态结束日期计算:每个计划的实际结束日取「自身计划结束日」和「下一个计划起始日的前一天」的较小值,既保证计划不重叠,又保留短周期计划的完整时间范围。
- 逐计划生成序列:为每个计划单独生成日期序列,自然保留同一天启动的多个计划记录。
内容的提问来源于stack exchange,提问作者Gabe Verzino
相关产品推荐
相关产品推荐

