4. 测井数据加载与质量检查实战

页岩储层脆性指数计算的第一步不是套公式,而是把测井曲线“干净地”装进来。脆性指数通常由矿物组分或弹性参数两条路线求取,无论哪条路线,都依赖 GR、DEN、AC、CNL、电阻率等基础曲线在同一深度采样体系下彼此对齐、量纲正确、无异常跳点。本节以一口实际页岩井的常规测井资料为对象,走完“加载—对齐—异常识别—缺失处理”的完整链路,并给出可直接复用的检查清单。

一、加载:先统一深度与采样

测井数据常见格式有 LAS 2.0、DLIS 和 CSV 导出表。教学示例中我们使用一份 LAS 2.0 文件,井段 2500–3200 m,包含 GR(API)、DEN(g/cm³)、AC(μs/ft)、CNL(%)、RT(Ω·m)五条曲线。加载时最容易出问题的不是读取本身,而是三件事:深度方向(多数测井曲线深度自上而下递增,但个别导出文件为递减)、采样间隔(GR 常为 0.125 m,DEN/AC 可能为 0.15 m 或 0.1 m)、空值与单位(LAS 中 -999.25 常代表无效值,AC 有 μs/ft 与 μs/m 两种单位)。

用 Python 加载并做基础规整的示例代码如下(示例参数,非实测结果):

import lasio, numpy as np, pandas as pd

las = lasio.read("well_A.las")
df = las.df().reset_index().rename(columns={"DEPT": "depth"})

# 1) 统一深度方向:确保自上而下递增
if df["depth"].iloc[0] > df["depth"].iloc[-1]:
    df = df.sort_values("depth").reset_index(drop=True)

# 2) 无效值替换
df = df.replace(-999.25, np.nan)

# 3) 单位统一:AC 若为 μs/m 则换算为 μs/ft
if las.curves["AC"].unit == "US/M":
    df["AC"] = df["AC"] / 3.28084

# 4) 重采样到统一 0.125 m 网格(线性插值,仅对连续型曲线)
grid = np.arange(df["depth"].min(), df["depth"].max(), 0.125)
df = df.set_index("depth").reindex(grid).interpolate(method="index").reset_index()
df.columns = ["depth", "GR", "DEN", "AC", "CNL", "RT"]

重采样只对 GR、DEN、AC、CNL、RT 这类连续曲线做线性插值;若后续引入岩性解释成果等离散曲线,必须用“最近邻”而非线性插值,否则会把相邻层的岩性标签抹平。

二、深度对齐:以标志层为锚

不同测井作业可能分次下井,深度系统存在系统性偏移。判断方法不是看曲线“好不好看”,而是找区域性标志层——页岩段内高 GR、高 AC、低 DEN 的富有机质层,或稳定泥岩段。把各曲线在该标志层的响应深度对齐,若偏移超过 0.5 m,需整体平移校正。下图展示了本节数据处理的完整链路与关键判断点:

页岩井测井数据加载与质量检查链路 ① 加载 LAS GR / DEN / AC CNL / RT -999.25 → NaN ② 深度对齐 方向统一(递增) 重采样 0.125 m 标志层偏移 ≤ 0.5 m ③ 异常识别 GR 0–300 API DEN 1.8–2.9 g/cm³ 跳点 / 尖峰 / 平直段 ④ 缺失处理 短缺口插值 长缺口标记 不参与脆性计算 曲线质量示意(深度向下增大) 2500 3200 GR DEN 尖峰 AC 缺失段 关键判断阈值(示例) • GR:0–300 API,>300 视为异常或刻度错误 • DEN:1.8–2.9 g/cm³,<1.8 多为井壁垮塌影响 • AC:40–200 μs/ft,突变 >30% 判为跳点 • CNL:-5%–60%,负值需核查刻度 • RT:对数坐标,突变两个数量级需复核 • 连续缺失 >2 m:标记为“不可用段” • 短缺口 ≤0.5 m:线性插值补齐

三、异常值识别:用物理范围加统计双保险

异常值分两类:物理不可能值和统计离群值。前者靠量纲与经验范围直接卡,例如 DEN 小于 1.8 g/cm³ 在页岩段几乎一定是井壁垮塌或仪器贴壁不良造成的低密度假象;GR 出现负值或超过 300 API 多为刻度或单位问题。后者用滑动窗口的稳健统计量识别,推荐用中位数绝对偏差(MAD)而非标准差,因为标准差本身会被尖峰拉偏:

def mad_outlier(s, win=21, k=4.0):
    med = s.rolling(win, center=True, min_periods=5).median()
    mad = (s - med).abs().rolling(win, center=True, min_periods=5).median()
    return (s - med).abs() > k * 1.4826 * mad

df["DEN_bad"] = mad_outlier(df["DEN"]) | ~df["DEN"].between(1.8, 2.9)
df.loc[df["DEN_bad"], "DEN"] = np.nan

注意:识别出的异常值应置为 NaN 再走缺失处理,而不是直接删除整行,否则会破坏深度网格的连续性,后续重采样又会引入新的错位。另外要区分“真异常”与“真实地质响应”:页岩段内 AC 突然升高可能是富有机质层,不能一律当噪声剔除,需结合 GR 同步升高、DEN 同步降低综合判断。

四、缺失值处理:按缺口长度分级

处理策略取决于缺口长度和曲线用途。对脆性指数计算而言,DEN 与 AC 是弹性参数路线的核心输入,缺失会直接导致该深度点无法计算,因此:短缺口(≤0.5 m,约 4 个采样点)用线性插值补齐;中等缺口(0.5–2 m)可用同层段相邻曲线的回归关系估算,例如用 GR 与 DEN 在正常段的线性拟合补 DEN;长缺口(>2 m)不做插值,标记为不可用段,在最终脆性指数曲线上留空,避免用虚假数据污染选段结论。

处理完成后必须做一次回检:统计各曲线有效样本占比、最大连续缺失长度、异常值剔除数量,并与处理前对比。下表为示例井段的检查记录(数值为教学示例,非实测):

曲线原始采样点异常剔除插值补齐长缺口标记有效占比
GR56011236099.1%
DEN560148601 段 / 3.2 m97.9%
AC560125481 段 / 2.6 m98.4%
CNL56011824099.2%
RT56013012099.2%
质量检查的通过标准建议设为:核心曲线(DEN、AC)有效占比 ≥95%,单段连续缺失 ≤2 m,且异常剔除后曲线在标志层处的响应与邻井一致。未达标时优先回查原始 LAS 的单位与刻度,而不是急于插值。
常见误区:把 -999.25 当作真实低值参与统计,会严重拉低 DEN 均值并误判异常;对离散岩性曲线做线性插值会产生不存在的过渡岩性;深度递减文件未排序就重采样,会导致整条曲线上下颠倒。这三类错误在脆性指数计算前必须排除。

完成上述四步后,得到的是一份深度网格统一、量纲一致、异常已标记、缺失有交代的曲线数据集,可直接进入下一环节的矿物组分或弹性参数计算。建议把本节的处理脚本与检查表固化为每口井的例行流程,保证不同井之间脆性指数结果具有可比性。