MIT-BIH 心律失常数据库 v1.0.0 数据解析实战:从 .dat 二进制到 CSV 的 3 步转换

📅 2026/7/6 12:32:54
MIT-BIH 心律失常数据库 v1.0.0 数据解析实战:从 .dat 二进制到 CSV 的 3 步转换
MIT-BIH 心律失常数据库二进制数据解析实战指南对于从事心电信号分析的研究人员和算法工程师而言MIT-BIH心律失常数据库是验证算法性能的黄金标准。但原始数据以特殊的二进制格式存储直接处理需要掌握特定技巧。本文将手把手带您完成从.dat/.atr文件到结构化CSV的完整转换流程。1. 环境准备与数据获取处理MIT-BIH数据前需要配置合适的工具链。推荐使用Python 3.8环境主要依赖库包括pip install wfdb numpy pandas matplotlib数据库文件可从PhysioNet官网获取包含三种关键文件类型.hea头文件ASCII格式.dat信号数据二进制格式.atr专家注释二进制格式典型文件结构示例100.hea # 头文件 100.dat # 信号数据 100.atr # 注释文件提示下载时确保同名文件的三个版本同时存在WFDB库读取时需要完整文件组2. 212格式解析核心原理MIT-BIH采用独特的212存储格式其技术特点包括采样规格采样率360Hz/通道分辨率11位ADC电压范围±5mV1024对应0V存储方案每3字节存储2个12位采样值字节排列[Byte1][Byte2][Byte3]→[Val1高8位][Val1低4位Val2高4位][Val2低8位]解码Python实现def decode_212(data): samples [] for i in range(0, len(data), 3): byte1, byte2, byte3 data[i:i3] # 第一个采样值 val1 (byte1 4) | (byte2 4) if val1 2047: # 处理11位有符号数 val1 - 4096 # 第二个采样值 val2 ((byte2 0x0F) 8) | byte3 if val2 2047: val2 - 4096 samples.extend([val1, val2]) return samples电压值转换公式电压(mV) 采样值 × (增益 / ADC分辨率)其中标准增益为200 units/mV3. 完整数据处理流程3.1 使用WFDB库读取专业生物信号库WFDB提供直接读取接口import wfdb # 读取记录100 record wfdb.rdrecord(100, sampfrom0, sampto1000) annotation wfdb.rdann(100, atr) # 获取信号数据 signals record.p_signal # 形状为(N,2)的numpy数组 fs record.fs # 采样率 # 获取注释信息 ann_samples annotation.sample # 注释位置 ann_symbols annotation.symbol # 注释符号3.2 手动解析实现对于需要深度定制的场景可手动实现解析def read_hea(hea_file): with open(hea_file) as f: lines [line.strip() for line in f] info { record: lines[0].split()[0], channels: int(lines[0].split()[1]), samples: int(lines[0].split()[2]), fs: int(lines[0].split()[3]), gain: [float(line.split()[2].split(/)[0]) for line in lines[1:3]] } return info二进制文件读取示例import struct def read_dat(dat_file, samples): with open(dat_file, rb) as f: data f.read() # 每3字节包含2个采样点 points samples * 3 // 2 fmt f{points}B # 小端字节序 return struct.unpack(fmt, data[:points])3.3 转换为CSV格式最终转换代码示例import pandas as pd def save_as_csv(record_id, output_file): signals wfdb.rdrecord(record_id).p_signal annotations wfdb.rdann(record_id, atr) df pd.DataFrame({ MLII: signals[:, 0], V1: signals[:, 1], annotation: [] * len(signals) }) for samp, sym in zip(annotations.sample, annotations.symbol): if samp len(df): df.at[samp, annotation] sym df.to_csv(output_file, index_labelsample)4. 实战技巧与异常处理常见问题解决方案问题现象可能原因解决方案读取数据为直线增益设置错误检查.hea文件中的ADC零值(通常为1024)注释位置偏移采样率不匹配确认fs360Hz与注释文件一致信号幅度异常导联类型差异MLII通常比V1导联幅度大20%-30%高级处理建议使用重采样对齐不同采样率的注释对噪声段应用Butterworth带通滤波(0.5-40Hz)使用插值处理缺失采样点from scipy import signal def filter_ecg(data, fs360): b, a signal.butter(4, [0.5, 40], btypebandpass, fsfs) return signal.filtfilt(b, a, data)通过本方案您将获得包含原始信号和专家注释的结构化CSV可直接用于机器学习建模或进一步分析。这种转换既保留了原始数据的精度又极大简化了后续处理流程。