3. 工程数据导入与接口
工程数据分析的第一步往往不是建模,而是把散落在不同载体里的数据可靠地读进 MATLAB 工作区。工程现场的数据来源通常高度异构:试验室台账多为 Excel,采集系统导出 CSV,设备日志是带时间戳的文本,历史工况存在数据库,而在线监测则来自传感器串口或网络流。本节围绕“读得进、读得对、读得可追溯”三个目标,梳理 MATLAB 中对应的接口与关键参数。
一、先判断数据形态,再选读取函数
选择读取方式的核心依据是:数据是规则表格还是非规则文本、是否含表头与单位行、数值与文本是否混排、文件规模有多大。规则二维表优先用 readtable,它能自动识别变量名与类型,返回 table 便于按列名访问;纯数值矩阵可用 readmatrix;需要保留原始文本行、处理非规则日志时用 readlines 或 fgetl 逐行解析;数据库走 Database Toolbox 的 database/fetch;实时传感器则用 serialport 或 tcpclient 建立流式接口。
二、Excel 与 CSV:把“表头陷阱”处理干净
工程 Excel 常见问题是前几行是标题、单位或合并单元格,真正的表头在第 3 行。此时应显式指定参数,而不是依赖自动识别:
opts = detectImportOptions('test_data.xlsx', ...
'Sheet','Sheet1', 'Range','A3:F200', ...
'VariableNamingRule','preserve');
opts.VariableTypes = {'datetime','double','double','double','double','string'};
T = readtable('test_data.xlsx', opts);
其中 VariableNamingRule 设为 preserve 可保留“转速(rpm)”这类含括号和中文的列名,避免被自动改成非法标识符。VariableTypes 显式声明类型,能防止“时间列被读成文本”或“含空值的数值列被读成 cell”。CSV 若使用分号分隔、小数点用逗号(欧洲格式),需设置 Delimiter',';' 与 DecimalSeparator',',',否则数值会整列变成字符串。
三、文本与传感器日志:按行解析再结构化
设备日志通常形如 2024-05-12 08:31:02.145, RPM=1480.2, TEMP=76.4, VIB=2.31。这类非规则文本不适合直接 readtable,应逐行读取后用正则提取:
lines = readlines('sensor_log.txt');
pat = '(\S+ \S+),\s*RPM=([\d.]+),\s*TEMP=([\d.]+),\s*VIB=([\d.]+)';
tok = regexp(lines, pat, 'tokens', 'once');
ok = ~cellfun(@isempty, tok);
t = datetime(cellfun(@(c) c{1}, tok(ok), 'uni', 0), ...
'InputFormat','yyyy-MM-dd HH:mm:ss.SSS');
rpm = cellfun(@(c) str2double(c{2}), tok(ok));
temp = cellfun(@(c) str2double(c{3}), tok(ok));
vib = cellfun(@(c) str2double(c{4}), tok(ok));
TT = timetable(rpm, temp, vib, 'RowTimes', t);
关键点是先用 ok 掩码剔除解析失败的行(如设备重启提示行),再统一构造 timetable。若日志时间戳无时区,应在导入时用 TimeZone 属性显式声明,避免后续多源合并时出现 8 小时偏移。
四、数据库与实时流:连接、查询与回调
数据库导入先建立连接再取数,示例(需已配置 JDBC 驱动):
conn = database('plantdb','user','pwd', ...
'Vendor','MySQL','Server','10.20.3.15','PortNumber',3306);
sql = ['SELECT ts, rpm, temp FROM run_log ' ...
'WHERE ts BETWEEN ''2024-05-01'' AND ''2024-05-31'''];
rows = fetch(conn, sql);
close(conn);
TT = table2timetable(rows, 'RowTimes','ts');
实时传感器用 serialport 打开端口并注册回调,把每帧数据追加进缓冲区,避免阻塞主流程:
s = serialport('COM5', 115200, 'Timeout', 2);
configureTerminator(s, 'CR/LF');
s.UserData = timetable();
configureCallback(s, 'terminator', @(~,~) appendFrame(s));
% appendFrame 内:readline -> 解析 -> 追加到 s.UserData
五、导入后的自检清单
数据读进来不等于读对了。建议每次导入后执行四项检查:一是行数与源文件记录数是否一致;二是时间列是否单调递增、有无重复或跳变;三是数值列的极值与量程是否合理(如转速不应为负、温度不应超过 200 ℃);四是缺失值比例,若某测点缺失超过 5% 需在报告中标注。可用 summary(TT) 快速查看各列类型、缺失与分位数,用 isregular(TT) 判断采样是否等间隔。只有通过自检的数据,才适合进入后续清洗与特征提取环节。
synchronize,否则后续趋势对比会得出错误结论。