使用Python Pandas为问题日志按日期标注各状态对应的层级耗时
需求描述
我有一份记录问题在不同时间节点变更情况的数据集,每条日志关联一个项目,包含多组不同项目的日志。需要为每条状态变更记录标注其所处的层级(新增Level Spent字段),使用Python的Pandas工具实现该需求。
单个项目示例输入数据
| Date | Field | Old Value | New Value |
|---|---|---|---|
| 2024-05-16 20:03:00 | Status | Development | QA |
| 2024-05-15 01:30:00 | Level | 3 | 2 |
| 2024-05-14 20:03:00 | Status | Work In Progress | Development |
| 2024-05-12 20:03:00 | Status | Investigate | Work in Progress |
| 2024-05-08 01:30:00 | Level | 4 | 3 |
| 2024-05-06 18:57:00 | Status | Scrub | Investigate |
| 2024-04-30 00:18:00 | Level | N/A | 4 |
期望输出结果
| Date | Field | Old Value | New Value | Level Spent |
|---|---|---|---|---|
| 2024-05-16 20:03:00 | Status | Development | QA | 2 |
| 2024-05-15 01:30:00 | Level | 3 | 2 | 2 |
| 2024-05-14 20:03:00 | Status | Work In Progress | Development | 3 |
| 2024-05-12 20:03:00 | Status | Investigate | Work in Progress | 3 |
| 2024-05-08 01:30:00 | Level | 4 | 3 | 3 |
| 2024-05-06 18:57:00 | Status | Scrub | Investigate | 4 |
| 2024-04-30 00:18:00 | Level | N/A | 4 | 4 |
实现思路
核心逻辑:每条记录的Level Spent等于该记录发生时当前生效的Level值。Level变更会影响后续所有记录,因此需按时间倒序处理,从最新的Level开始向前填充,确保每条记录获取对应生效Level。
具体步骤:
- 将
Date列转为datetime类型,保证时间排序准确 - 按项目分组(多项目场景),对每个项目的日志按
Date降序排列 - 提取Level变更记录的
New Value,向前填充到所有记录,得到每条记录对应的生效Level - 最后按原时间顺序排序,得到最终结果
Pandas代码实现
import pandas as pd # 示例数据(多项目场景需添加Project列) data = [ ["2024-05-16 20:03:00", "Status", "Development", "QA"], ["2024-05-15 01:30:00", "Level", "3", "2"], ["2024-05-14 20:03:00", "Status", "Work In Progress", "Development"], ["2024-05-12 20:03:00", "Status", "Investigate", "Work in Progress"], ["2024-05-08 01:30:00", "Level", "4", "3"], ["2024-05-06 18:57:00", "Status", "Scrub", "Investigate"], ["2024-04-30 00:18:00", "Level", "N/A", "4"], ] df = pd.DataFrame(data, columns=["Date", "Field", "Old Value", "New Value"]) # 转换日期格式 df["Date"] = pd.to_datetime(df["Date"]) def process_project_group(group): # 按日期降序排列,从最新记录开始处理 group_sorted = group.sort_values("Date", ascending=False).reset_index(drop=True) # 标记Level变更记录的新值,其余为缺失值 group_sorted["Level Spent"] = group_sorted.apply( lambda row: row["New Value"] if row["Field"] == "Level" else pd.NA, axis=1 ) # 向前填充缺失值,传递生效的Level值 group_sorted["Level Spent"] = group_sorted["Level Spent"].ffill() # 转为数值类型(按需调整) group_sorted["Level Spent"] = pd.to_numeric(group_sorted["Level Spent"], errors="coerce") # 恢复原时间顺序 return group_sorted.sort_values("Date").reset_index(drop=True) # 单个项目直接处理;多项目场景替换为:df.groupby("Project").apply(process_project_group).reset_index(drop=True) result_df = process_project_group(df) print(result_df)
代码说明
- 日期转换:避免字符串排序错误,确保时间顺序准确
- 降序排序:从最新记录开始处理,让Level变更的新值能覆盖更早的记录
- 向前填充:
ffill()方法将最近的非缺失值填充到前面的缺失位置,符合Level生效逻辑——一旦Level变更,后续所有更早的记录都使用该Level值 - 多项目适配:若数据集包含
Project列,只需修改分组逻辑即可自动按项目处理所有日志
内容的提问来源于stack exchange,提问作者Vokult
相关产品推荐
相关产品推荐

