阶段一 · 打好地基 · 模块 2 · 第 2 课 / 共 28 课

Matlab 编程基础:从变量到矩阵

EEG 数据在计算机里就是一个"电极 × 时间"的数字矩阵。这一课把 Matlab 讲到 "够用且理解数据结构"的程度——不追求语法大全,每一步都对着脑电数据讲。

🕐 45 分钟🎯 难度:入门✅ 前置:无

🎯 本节学习目标

  • 熟悉 Matlab 的四个核心窗口,学会用 helpdoc 自助查文档
  • 理解"一切皆矩阵",会用 []zeroslinspace 创建数据
  • 熟练使用索引与切片:M(2,3)M(:, 100:200)——这是读写 EEG 数据的基本功
  • 掌握 forif 与自定义函数,能看懂别人的批处理脚本
  • 会用 plotimagesc 画信号波形与数据热图

一、为什么脑电分析绕不开 Matlab

你可能听说过 Python 的 MNE,但现实是:国内绝大多数课题组的脑电流水线建立在 Matlab 生态上——EEGLAB、FieldTrip、ERPLAB、CARTOOL、sLORETA 全是 Matlab 工具包。 学会 Matlab,你就能直接使用这套学界积累了几十年的工具链,还能看懂师兄师姐留下的脚本。

好消息是:做脑电分析只需要 Matlab 的一小部分语法。这一课的目标不是"学会 Matlab",而是"让 Matlab 为脑电分析所用"

二、认识 Matlab 的四个窗口

窗口作用你会在什么时候用到
命令行窗口输入命令、立即看结果试探性操作:看看变量、画张图
编辑器写脚本(.m 文件)批处理、可复现的分析流程(模块 2.4 的主战场)
工作区查看当前内存里的变量检查 EEG 结构里有什么字段
当前文件夹文件浏览与路径管理数据文件;路径含中文/空格是常见报错来源
💡 自助查文档的两个命令

忘记函数用法时:help plot(快速摘要)和 doc plot(完整文档页)。养成这个习惯,比搜索更快。

三、变量与矩阵:EEG 数据的本来面目

Matlab 的核心数据结构是矩阵。一段脑电数据采集下来,就是这样一个矩阵: 行 = 电极通道,列 = 时间点。例如 64 通道、采样率 500Hz、记录 10 分钟的数据, 就是一个 64 × 300000 的矩阵(500 × 60 × 10 = 300000 个时间点)。

Matlab
% 创建变量:一行一个命令,分号结尾表示"执行但不显示结果"
a = 5;                          % 标量,其实是 1x1 矩阵
v = [10 20 30];                 % 行向量:3 个时间点的信号
M = [1 2 3; 4 5 6];             % 2 行 3 列矩阵:想象成 2 个电极 x 3 个时间点

% 常用构造函数
z = zeros(64, 1000);            % 64 通道 x 1000 时间点的全 0 矩阵
t = linspace(0, 1, 500);        % 0 到 1 秒之间的 500 个时间点(采样率 500Hz)

% 模拟一段"脑电":10Hz 的 alpha 波 + 随机噪声
fs = 500;                        % 采样率
time = (0:1/fs:2)';              % 2 秒的时间轴(列向量)
eeg = 10*sin(2*pi*10*time) + 5*randn(size(time));  % alpha 波 + 噪声(微伏)
plot(time, eeg);                 % 画出来看看
xlabel('时间 (s)'); ylabel('幅度 (\muV)'); title('模拟 EEG 信号');

四、索引与切片:读写数据的基本功

假设 EEGdata 是 64 × 300000 的数据矩阵(行=通道,列=时间点):

写法含义脑电场景举例
EEGdata(2, 500)第 2 通道第 500 个时间点的值查某个电极某一时刻的电位
EEGdata(2, :)第 2 通道的完整波形取出一个电极画整段波形
EEGdata(:, 1000:2000)所有通道、第 1000–2000 时间点截取 2 秒的数据段
EEGdata([1 2 3], :)指定多个通道只取 Fp1、Fp2、Fz 三个电极
EEGdata(1:32, :)前 32 个通道只用一半电极做快速测试
size(EEGdata)矩阵的尺寸确认通道数和数据长度对不对
📌 记住这个直觉

在 EEGLAB 里你点菜单,本质都是在操作这个矩阵:EEG.data 就是它。切片用熟了,后面写脚本会非常顺手。

五、矩阵运算:小心 *.* 的区别

Matlab 里 * 是矩阵乘法,.* 才是"对应元素相乘"。对脑电分析,90% 场景用的是点运算:

Matlab
a = [1 2 3];
b = [4 5 6];

a .* b      % [4 10 18]  每个元素对应相乘 —— 常用!
a * b       % 报错(维度不满足矩阵乘法规则)
a * b'      % 32:向量内积
a ./ b      % [0.25 0.4 0.5] 逐元素相除
a + 10      % [11 12 13] 广播运算:整体加 10(如单位换算 \muV 转 mV)

% 常见用途:把信号从微伏转成伏特、或做归一化
eeg_volts = eeg * 1e-6;
eeg_norm = eeg ./ max(abs(eeg));  % 除以最大绝对值,缩放到 [-1, 1]

六、流程控制:让重复劳动自动化

Matlab
% for 循环:对每个通道求均值和标准差,标记"噪声过大"的通道
channels = 1:64;
bad_list = [];                          % 用来收集坏通道编号
for ch = channels
    m = mean(EEGdata(ch, :));           % 该通道的平均电位
    sd = std(EEGdata(ch, :));           % 该通道的波动大小
    if sd > 100                         % 波动超过 100 \muV 视为可疑
        bad_list = [bad_list, ch];      % 记下来
    end
end
disp(['可疑通道: ' mat2str(bad_list)]); % 打印结果

这段代码就是"坏通道检测"的最小雏形——模块 2.4 的批处理脚本里, 循环的外层从"通道"换成"被试",就是完整的批处理了。

七、画图三件套

Matlab
% 1. plot:波形图(时间序列)
figure; plot(time, eeg);

% 2. imagesc:热图(矩阵可视化)—— 时频图、ERPimage 都靠它
figure; imagesc(randn(64, 500));            % 64 通道 x 500 时间点的伪彩色图
colorbar;

% 3. subplot:一页多图,对比不同条件
figure;
subplot(1, 2, 1); plot(time, eeg);  title('原始信号');
subplot(1, 2, 2); plot(time, smooth(eeg, 25)); title('平滑后');

% 保存图片(print 比 saveas 控制更细)
print('-dpng', '-r300', 'my_first_eeg_figure.png');
💡 论文图片建议

投稿图件用矢量格式(-depsc-dpdf)保存,放大不失真;给导师看预览用 PNG 即可。

八、五个必须养成的习惯

  1. 脚本开头写三连clear; clc; close all;——清空旧变量、清屏、关旧图,避免"上次运行残留"导致的诡异 bug。
  2. 写注释:一个月后的你等于陌生人。% 后面用一句话说明"为什么这么做"。
  3. 文件名只用英文:中文路径和空格是 EEGLAB/FieldTrip 报错的头号来源。
  4. 路径集中管理:数据、脚本、结果分三个文件夹,用 addpath 添加路径,别让文件散落桌面。
  5. 随手保存save('result.mat', 'eeg') 把中间结果存档;load('result.mat') 随时恢复。

📌 本节小结

  • EEG 数据 = 电极 × 时间的矩阵:EEGdata(通道, 时间点)
  • 切片 M(:, 100:200)、构造 zeros/linspace、尺寸 size() 是使用频率最高的四个操作
  • 点运算 .* ./ 用于逐元素计算,* 是矩阵乘法——两者不可混用
  • for + if 组合可以实现坏通道检测等自动检查逻辑,也是批处理脚本的骨架
  • 三个习惯省半天调试:开头三连、英文路径、随手 save

✏️ 课后练习

  1. 生成一个 64 × 1000 的随机矩阵 X,用 imagesc 画出热图,加上 colorbar 并保存为 PNG。
  2. X 的每个通道求标准差,找出标准差最大的 3 个通道编号(提示:std + sortmaxk)。
  3. linspace 生成 2 秒时间轴,叠加 10Hz 和 40Hz 两个正弦波(幅度分别为 10 和 5),画图后观察你能"目测"出几个波峰结构。