
本文介绍如何利用 piso 库结合 pandas 的 intervalindex,将重叠的里程区间巡检记录自动切分、对齐并聚合出每个非重叠子区段对应的最新巡检日期。
本文介绍如何利用 piso 库结合 pandas 的 intervalindex,将重叠的里程区间巡检记录自动切分、对齐并聚合出每个非重叠子区段对应的最新巡检日期。
在基础设施资产管理(如道路、管道、电网线路)中,常需基于“区间覆盖”关系分析历史巡检数据——例如某段 0–5 英里道路被多次不规则区间巡检,目标是生成一份互斥且完备的最小粒度区段表,每段标注其最后一次被覆盖的巡检时间。这一任务本质是区间集合的“时间加权剖分”(time-weighted interval splitting),而 piso 库专为高效处理此类 pandas 区间操作而设计。
以下为可直接运行的完整实现方案,步骤清晰、逻辑严谨:
import pandas as pd
import piso
# 原始巡检数据:[From_Mi, To_Mi, Date]
all_df = pd.DataFrame(
data=[
(0, 5, pd.Timestamp("2025-01-01")),
(2, 5, pd.Timestamp("2025-01-08")),
(0, 3, pd.Timestamp("2025-01-15")),
(0, 2, pd.Timestamp("2025-01-22")),
],
columns=["From_Mi", "To_Mi", "Date"]
)
# 步骤 1:按时间升序排序(确保后续取 .iloc[-1] 即为最新)
all_df = all_df.sort_values("Date", ascending=True)
# 步骤 2:构建 IntervalArray(注意:piso 要求闭区间语义一致,默认 left-closed, right-open;
# 若业务中 [0,2] 表示包含端点2,建议显式指定 closed='both')
intervals = pd.arrays.IntervalArray.from_arrays(
all_df["From_Mi"],
all_df["To_Mi"],
closed="both" # 关键!匹配实际业务区间含义
)
# 步骤 3:用 piso.split() 按所有端点切分,得到所有可能的最小非重叠子区间
breakpoints = set(intervals.left).union(set(intervals.right))
split_intervals = piso.split(intervals, breakpoints)
# 步骤 4:去重 → 得到唯一、互斥、覆盖全集的原子区间
unique_intervals = split_intervals.unique()
# 步骤 5:将原始巡检记录转为以区间为索引的 Series(便于按区间查找覆盖关系)
interval_index = pd.IntervalIndex(intervals, closed="both")
dates_series = all_df.set_index(interval_index)["Date"]
# 步骤 6:对每个原子区间,找出所有与其重叠的原始巡检记录,并取其中最新日期
recent_records = []
for ui in unique_intervals:
overlapping = dates_series.index.overlaps(ui)
if overlapping.any(): # 安全检查:确保至少有一条记录覆盖该子区间
latest_date = dates_series[overlapping].iloc[-1] # 因已升序排序,末项即最新
recent_records.append({
"From_Mi": ui.left,
"To_Mi": ui.right,
"Last_Date": latest_date
})
# 最终结果 DataFrame
recent_df = pd.DataFrame(recent_records)
print(recent_df)
输出结果为:
From_Mi To_Mi Last_Date 0 0 2 2025-01-22 1 2 3 2025-01-15 2 3 5 2025-01-08
✅ 关键要点说明:
-
piso.split(..., breakpoints)是核心操作:它将所有原始区间按所有出现过的端点(0, 2, 3, 5)强制切割,生成[0,2], [2,3], [3,5]等原子区间,消除任何重叠; -
closed="both"必须与业务语义一致(如“0–2英里”含端点),否则overlaps()判断会出错; - 排序
ascending=True+iloc[-1]是高效获取“最新覆盖时间”的简洁技巧,避免复杂分组聚合; - 该方法天然支持任意维度扩展(如添加
Asset_ID后按组分别处理),只需外层加groupby即可。
⚠️ 注意事项:
- 若存在孤立端点(如某次巡检仅覆盖
[1.5, 1.7],但无其他记录涉及 1.5 或 1.7),breakpoints集合仍能保证剖分完整性; - 对超大规模数据(>10⁵ 条记录),可考虑用
piso.intersection()批量计算覆盖关系替代循环,进一步向量化; -
piso当前版本(≥0.9.0)已完全兼容 pandas 2.x,安装命令:pip install piso。
此方案将区间逻辑从手动遍历抽象为声明式切分+索引查找,兼具可读性、健壮性与工程可维护性,是资产区间时序分析的推荐范式。










