1. 原始数据导入与完整性校验

原始数据长什么样,先看清再动手

岩石单轴压缩试验机(如 MTS、TAW 系列)导出的原始文件通常是纯文本或 CSV,每行一条采样记录,典型字段为:序号, 时间(s), 轴向载荷(kN), 轴向位移(mm)。导入前必须先确认三件事:列顺序与单位、采样频率、文件是否含表头与注释行。不同机型的位移单位可能是 mm 也可能是 μm,载荷可能是 kN 也可能是 N,单位错一位,后面算出的 UCS 就错三个数量级。

下面给出一个可直接运行的 Python 校验脚本。它不依赖任何第三方库,用标准库完成导入、逐项检查并输出质量报告。示例数据为教学构造的 12 行片段,用于演示各类异常如何被识别。

import csv, io, math

RAW = """# TAW-2000 export, unit: kN / mm
idx,time_s,load_kN,disp_mm
1,0.000,0.02,0.000
2,0.100,0.05,0.002
3,0.200,0.08,0.004
4,0.300,0.11,0.006
5,0.400,0.15,0.008
6,0.500,0.19,0.010
7,0.600,0.24,0.012
8,0.700,,0.014
9,0.800,0.31,0.016
10,0.900,0.36,0.018
11,1.000,0.41,0.020
12,1.100,0.47,0.022
"""

def load_rows(text):
    lines = [ln for ln in text.splitlines()
             if ln.strip() and not ln.lstrip().startswith("#")]
    reader = csv.DictReader(io.StringIO("\n".join(lines)))
    rows = []
    for r in reader:
        rows.append({
            "idx": int(r["idx"]),
            "t": float(r["time_s"]),
            "P": None if r["load_kN"].strip() == "" else float(r["load_kN"]),
            "d": None if r["disp_mm"].strip() == "" else float(r["disp_mm"]),
        })
    return rows

def check(rows, dt_nom=0.1, P_max=2000.0, d_max=10.0):
    rep = {"n": len(rows), "issues": []}
    # 1) 时间戳连续性
    gaps = []
    for a, b in zip(rows, rows[1:]):
        dt = round(b["t"] - a["t"], 6)
        if abs(dt - dt_nom) > 1e-6:
            gaps.append((a["idx"], b["idx"], dt))
    if gaps:
        rep["issues"].append(("时间戳不连续", gaps))
    # 2) 缺失值
    miss = [(r["idx"], k) for r in rows for k in ("P", "d") if r[k] is None]
    if miss:
        rep["issues"].append(("缺失值", miss))
    # 3) 量程溢出
    over = [(r["idx"], r["P"], r["d"]) for r in rows
            if (r["P"] is not None and abs(r["P"]) > P_max)
            or (r["d"] is not None and abs(r["d"]) > d_max)]
    if over:
        rep["issues"].append(("量程溢出", over))
    # 4) 单调性(位移应非减)
    back = [(a["idx"], b["idx"]) for a, b in zip(rows, rows[1:])
            if a["d"] is not None and b["d"] is not None and b["d"] < a["d"]]
    if back:
        rep["issues"].append(("位移回退", back))
    return rep

rows = load_rows(RAW)
rep = check(rows)
print("采样点数:", rep["n"])
for name, detail in rep["issues"]:
    print(f"[{name}] {detail}")

对示例数据运行后,报告会指出:采样点数 12;第 8 条记录载荷缺失(缺失值 [(8,'P')]);时间戳间隔均为 0.1 s,无断点;无溢出、无位移回退。这说明该片段只有一处缺失,处理策略是标记而非删除——保留行号,在后续插值或剔除时按区段处理,避免索引错位。

采样点数与采样频率要交叉验证:若文件头声明 10 Hz,而实际时间间隔为 0.1 s,则一致;若声明 50 Hz 却仍是 0.1 s,说明导出时被降采样,需在报告中注明,否则峰值载荷可能被漏采。

异常区段的判定与标记

校验的目的不是把异常行删掉,而是给出可追溯的区段标记。建议在报告中为每类异常记录起止行号、异常类型、涉及字段和建议动作(保留/插值/剔除)。例如:

  • 缺失值:单点缺失可线性插值;连续缺失超过 3 点应整段剔除并记录。
  • 时间戳断点:若 dt 为标称值的整数倍,说明丢帧,按丢帧数补记;若 dt 非整数倍,检查是否混入其他试验段。
  • 量程溢出:载荷接近传感器满量程时可能削顶,该区段峰值不可信,应标记为“饱和区”。
  • 位移回退:单轴压缩中位移应单调不减,回退通常意味着压头回程或数据错位,需剔除。
导入与校验链 试验机导出文件 txt / csv + 注释行 解析表头与单位 kN / mm 确认 逐行读入 idx,t,P,d 四项检查 点数/时间/溢出/缺失 质量报告 + 区段标记 保留/插值/剔除 示例片段(12 点)与异常定位 idx t (s) P (kN) d (mm) 状态 10.0000.020.000正常 20.1000.050.002正常 30.2000.080.004正常 40.3000.110.006正常 50.4000.150.008正常 60.5000.190.010正常 70.6000.240.012正常 80.700—0.014缺失值 90.8000.310.016正常 100.9000.360.018正常 111.0000.410.020正常 121.1000.470.022正常 检查结论:n=12 | Δt 恒为 0.100 s(连续)| 无溢出 | 位移单调 | 1 处缺失(idx=8, P) 建议动作:idx=8 载荷线性插值(0.24→0.31 中点 0.275 kN),保留行号以便追溯

质量报告应包含的字段

报告不必复杂,但必须能支撑后续处理决策。建议至少包含:文件路径与哈希(保证可追溯)、总行数、有效采样点数、标称采样频率与实测中位时间间隔、各字段缺失计数、溢出计数与首次溢出位置、位移回退次数、异常区段列表(起止 idx、类型、建议动作)。把这份报告与原始文件一起归档,后续任何剔除或插值操作都能回溯到具体行号。

不要在校验阶段直接修改原始文件。所有插值、剔除都应写入新文件或新列,原始数据保持只读,否则一旦处理出错将无法复现。

完成本节后,你应能拿到一份明确的“数据可用性结论”:哪些区段可直接使用、哪些需插值、哪些必须剔除。这个结论是后续去噪、柔度修正和 UCS 计算的输入前提。