基于条件拆分Pandas DataFrame行:按小时拆分可拆分任务
问题:Pandas任务拆分实现方案
原始DataFrame
import pandas as pd df = pd.DataFrame({ "Jobs": ["Signature", "Verification", "Train", "Test"], "Total_Duration_(seconds)": [17000, 4000, 6000, 3500], "#_of_items": [100, 20, 50, 12], "Job_divisible": [1, 0, 1, 1] })
需求说明
当Job_divisible为1(任务可拆分)时:
- 若总时长超过3600秒(1小时),拆分为多个1小时子任务,最后一个子任务保留剩余时长
- 同时按比例拆分
#_of_items列的值,保证拆分后item总数与原数据一致
期望输出
Jobs Total_Duration_(seconds) #_of_items 0 Signature_1 3570 21 1 Signature_2 3570 21 2 Signature_3 3570 21 3 Signature_4 3570 21 4 Signature_5 2720 16 5 Verification 4000 20 6 Train_1 3600 30 7 Train_2 2400 20 8 Test 3500 12
解决方案
通过自定义拆分函数结合apply和explode实现,代码如下:
import pandas as pd def split_job(row): # 不可拆分或时长未超1小时,直接返回原行数据 if row["Job_divisible"] != 1 or row["Total_Duration_(seconds)"] <= 3600: return [{"Jobs": row["Jobs"], "Total_Duration_(seconds)": row["Total_Duration_(seconds)"], "#_of_items": row["#_of_items"]}] total_duration = row["Total_Duration_(seconds)"] total_items = row["#_of_items"] job_name = row["Jobs"] # 计算全量1小时任务的数量和剩余时长 num_full_tasks = total_duration // 3600 remaining_duration = total_duration % 3600 # 按比例计算每个全量任务的item数(取整) item_per_full = round(total_items * 3600 / total_duration) # 构造子任务的名称、时长、item数列表 job_names = [f"{job_name}_{i+1}" for i in range(num_full_tasks)] durations = [3600] * num_full_tasks items = [item_per_full] * num_full_tasks # 添加剩余任务(若有剩余时长) if remaining_duration > 0: job_names.append(f"{job_name}_{num_full_tasks+1}") durations.append(remaining_duration) items.append(total_items - sum(items)) # 返回子任务字典列表 return [{"Jobs": jn, "Total_Duration_(seconds)": d, "#_of_items": it} for jn, d, it in zip(job_names, durations, items)] # 应用拆分函数并展开结果 result_df = df.apply(split_job, axis=1).explode().apply(pd.Series).reset_index(drop=True) print(result_df)
代码说明
- 自定义拆分函数:
- 先判断任务是否满足拆分条件,不满足则直接返回原行
- 计算全量任务数量和剩余时长,按比例分配item数,最后用总item数减去全量任务的item数和,保证剩余任务的item数准确
- 结果展开:
- 用
apply对每行执行拆分逻辑,得到子任务列表 - 通过
explode将列表拆分为多行,再转换为DataFrame并重置索引
- 用
内容的提问来源于stack exchange,提问作者Salih
相关产品推荐
相关产品推荐

