2. 雷达位移数据时间序列对齐与重采样
为什么时间戳不一致会让预警序列错位
多台边坡雷达往往由不同厂商、不同批次部署,采样间隔可能是 6 min、10 min 或 30 min,且各台设备的时钟存在秒级到分钟级漂移。若直接把两台雷达的位移序列按行号拼接或按“第 n 个点”对齐,就会出现同一时刻的位移被错配到相邻时刻,导致合成速率、阈值判定和预警等级整体偏移。本节的任务是:把多源位移序列统一到一条规则时间基准上,并给出可验证的对齐结果。
统一时间基准与重采样策略
工程上通常选一个“主基准”:以采样最密、时钟最可信的一台雷达的采样时刻作为公共时间轴,或直接构造固定步长的规则时间轴(如 10 min)。对齐分两步:
- 时间对齐:把各序列的时间戳归一到同一时区与同一格式(建议统一为 UTC 毫秒或 ISO 8601),并处理重复时间戳(同测点同一时刻取均值或保留最后一条)。
- 重采样:对规则时间轴上的每个时刻,用“前向保持(ffill)+ 最大容忍间隔”或“线性插值”取值。位移是缓变量,线性插值通常可接受;但跨越长时间断档(如设备离线)时不应插值,应标记为缺失,避免伪造位移。
关键约束:插值只允许在相邻有效点间隔不超过
max_gap(例如 2 倍标称采样间隔)时进行;超过则输出 NaN 并记录断档,供后续清洗与预警模块识别。可运行的 Python 实现
下面用 pandas 完成对齐与重采样。示例数据为教学构造,时间戳与位移值均为假设值,用于演示处理逻辑,不代表真实监测结果。
import pandas as pd
import numpy as np
# 教学示例:三台雷达的原始位移记录(时间戳为假设值)
raw = {
"A": pd.DataFrame({
"ts": pd.to_datetime(["2024-06-01 00:00","2024-06-01 00:06","2024-06-01 00:12",
"2024-06-01 00:18","2024-06-01 00:24","2024-06-01 00:30"]),
"disp": [10.0, 10.6, 11.1, 11.9, 12.4, 13.0]}),
"B": pd.DataFrame({
"ts": pd.to_datetime(["2024-06-01 00:03","2024-06-01 00:13",
"2024-06-01 00:23","2024-06-01 00:33"]),
"disp": [10.3, 11.2, 12.1, 13.2]}),
"C": pd.DataFrame({
"ts": pd.to_datetime(["2024-06-01 00:00","2024-06-01 00:06",
"2024-06-01 00:24","2024-06-01 00:30"]),
"disp": [9.8, 10.4, 12.2, 12.9]}),
}
STEP = "10min" # 统一时间基准步长
MAX_GAP = "20min" # 允许插值的最大相邻间隔(2 倍标称间隔)
def align_one(df, step=STEP, max_gap=MAX_GAP):
df = df.sort_values("ts").drop_duplicates("ts", keep="last").set_index("ts")
# 规则时间轴:从最早到最晚,按 step 生成
axis = pd.date_range(df.index.min(), df.index.max(), freq=step)
# 先重采样到规则轴,再按间隔限制插值
s = df["disp"].reindex(df.index.union(axis)).interpolate(method="time")
s = s.reindex(axis)
# 计算每个目标时刻与最近有效原始点的间隔,超限置 NaN
orig = df["disp"]
gap = pd.Series(index=axis, dtype="timedelta64[ns]")
for t in axis:
if t in orig.index:
gap[t] = pd.Timedelta(0)
else:
prev = orig.index[orig.index <= t].max() if (orig.index <= t).any() else pd.NaT
nxt = orig.index[orig.index >= t].min() if (orig.index >= t).any() else pd.NaT
d = min([abs(t - prev) if pd.notna(prev) else pd.Timedelta("999D"),
abs(nxt - t) if pd.notna(nxt) else pd.Timedelta("999D")])
gap[t] = d
s[gap > pd.Timedelta(max_gap)] = np.nan
return s
aligned = pd.DataFrame({k: align_one(v) for k, v in raw.items()})
print(aligned)
运行后得到统一 10 min 时间轴上的三列位移。雷达 C 在 00:10、00:20 两个时刻因断档超过 max_gap 被置为 NaN,而 A、B 通过时间插值补齐。这样后续速率计算与阈值判定就不会把不同时刻的位移混在一起。
对齐结果的验证要点
| 检查项 | 通过条件 | 不通过时的处理 |
|---|---|---|
| 时间轴唯一性 | 索引严格递增、无重复 | 去重时保留最后一条并记录 |
| 序列长度一致 | 各雷达列长度相同 | 检查时间轴生成范围是否覆盖全部设备 |
| 断档标记 | NaN 位置与断档日志一一对应 | 核对 max_gap 设置是否过宽 |
| 插值合理性 | 插值点位于相邻实测值之间 | 检查是否误用了跨断档插值 |
不要用“按行号对齐”替代时间对齐;也不要在断档区间强行插值,否则会生成虚假的连续位移,直接污染后续速率与预警判定。