一、什么是 MNE-Python?
MNE 全称是Magnetoencephalography and Electroencephalography Neuroimaging Engineering,是专门用于分析脑电图(EEG) 和**脑磁图(MEG)**数据的 Python 工具包。
简单来说,它能帮我们:
-
📂 读取各种格式的脑电数据
-
🧹 清理数据中的噪声和伪迹
-
📊 分析和提取有意义的脑电特征
-
🎨 绘制漂亮的脑电图表
二、环境搭建
python
pip install mne -i https://pypi.tuna.tsinghua.edu.cn/simple
三、下载练习数据集
MNE 官方提供了免费的示例数据集,大约 2GB,包含真实实验数据:
python
import mne
import matplotlib.pyplot as plt
# 下载样本数据集(只需下载一次,之后直接调用)
sample_data_folder = mne.datasets.sample.data_path()
print(f"数据集存放位置: {sample_data_folder}")
数据集里有什么?
-
👂 听觉刺激反应(被试听声音时的脑电)
-
👁️ 视觉刺激反应(被试看图像时的脑电)
-
💪 运动想象数据(被试想象运动时的脑电)
四、认识 Raw 对象 - 脑电数据的"身份证"
4.1 什么是 Raw 对象?
RAW 对象存储的是原始的连续脑电数据,可以理解为一张大表格:
行 :每个通道(电极)的数据 列:每个时间点的采样值
4.2 加载原始数据
python
import os
# 构建数据文件路径
raw_fname = os.path.join(sample_data_folder, 'MEG', 'sample', 'sample_audvis_raw.fif')
# 加载数据
raw = mne.io.read_raw_fif(raw_fname, preload=False)
print("✅ 数据加载成功!")

4.3 查看数据基本信息
这是认识数据的第一步,就像拿到一本书先看封面和目录:
python
# 1. 查看完整信息
print(raw.info)

python
# 2. 提取关键参数
print(f"采样率:{raw.info['sfreq']} Hz")
print(f"通道数:{len(raw.ch_names)}")
print(f"数据时长:{raw.times[-1]:.0f} 秒(约{raw.times[-1]/60:.1f}分钟)")
raw.times 的下标是"第几个点",值是这个点对应的时刻。
4.4 理解通道类型
脑电数据中有不同类型的通道,各自作用不同:

python
# 查看通道类型统计
from collections import Counter
ch_types = raw.get_channel_types()
type_counts = Counter(ch_types)
print("通道类型统计:")
for ch_type, count in type_counts.items():
print(f" {ch_type}: {count} 个")
五、数据的基本操作(CRUD)
5.1 复制数据
python
# 养成好习惯:操作前先复制,保留原始数据
raw_copy = raw.copy()
5.2 裁剪数据(选择时间段)
python
# 只看第 60 秒到 120 秒的数据
raw_cropped = raw.copy().crop(tmin=60, tmax=120)
print(f"裁剪后时长:{raw_cropped.times[-1] - raw_cropped.times[0]:.0f} 秒")
为什么要裁剪?
(1)原始数据太长,分析时只关注特定时间段
(2)去掉开头和结尾的质量不好的部分
5.3 选择通道
python
# 方法1:选择前 10 个通道
raw_subset = raw.copy().pick([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 方法2:选择特定类型的通道
raw_eeg = raw.copy().pick_types(eeg=True) # 只要 EEG 通道
5.4 查看数据矩阵
python
# 获取所有数据(通道数 × 时间点数)
data, times = raw[:, :]
print(f"数据矩阵形状:{data.shape}")
print(f" → {data.shape[0]} 个通道 × {data.shape[1]} 个时间点")

六、数据可视化 - 让数据"说话"
6.1 时间序列图(最重要)
查看脑电波随时间的变化:
python
# 显示前 60 秒,10 个通道
raw.plot(duration=60, n_channels=10, scalings='auto', block=True)

6.2 查看特定时间段
python
start_time = 100
duration = 30
# 先裁剪,再绘制
raw_segment = raw.copy().crop(tmin=start_time, tmax=start_time + duration)
raw_segment.plot(n_channels=20, duration=duration,
scalings='auto', block=True,
title=f'第{start_time}秒到{start_time+duration}秒')
6.3 功率谱密度图(PSD)
显示不同频率的能量分布:
python
raw.plot_psd(fmin=0.5, fmax=50, spatial_colors=True)
plt.title('功率谱密度 - 各频率的能量分布')
plt.show(block=True)

6.4 通道位置图
查看电极在头皮上的排列:
python
# 2D 平面图
raw.plot_sensors(show_names=True, title='电极位置(10-20系统)', block=True)
# 3D 立体图(需要安装 pyvista)
# pip install pyvista -i https://pypi.tuna.tsinghua.edu.cn/simple
七、完整代码示例
这是今天的完整学习代码,可以直接复制运行:
python
# ========== 必须放在最开头 ==========
import matplotlib
matplotlib.use('TkAgg')
# ===================================
import matplotlib.pyplot as plt
import mne
import numpy as np
import os
from collections import Counter
print("="*60)
print("📘 MNE-Python 第1天:环境搭建与数据初探")
print("="*60)
# ---------- 1. 下载和加载数据 ----------
print("\n步骤1:下载示例数据集...")
sample_data_folder = mne.datasets.sample.data_path()
raw_fname = os.path.join(sample_data_folder, 'MEG', 'sample', 'sample_audvis_raw.fif')
print("步骤2:加载数据...")
raw = mne.io.read_raw_fif(raw_fname, preload=False)
print("✅ 数据加载成功!")
# ---------- 2. 查看数据基本信息 ----------
print("\n" + "="*60)
print("📊 数据基本信息")
print("="*60)
print(f"采样率: {raw.info['sfreq']} Hz")
print(f"通道总数: {len(raw.ch_names)}")
print(f"数据时长: {raw.times[-1]:.0f} 秒 ({raw.times[-1]/60:.1f} 分钟)")
print(f"采样点数: {len(raw.times)}")
print("\n前 10 个通道名称:")
for i, name in enumerate(raw.ch_names[:10]): #enumerate():为每个通道名添加索引编号(从0开始)
print(f" {i}: {name}")
# ---------- 3. 通道类型统计 ----------
print("\n通道类型统计:")
ch_types = raw.get_channel_types()
type_counts = Counter(ch_types)
for ch_type, count in type_counts.items():
print(f" {ch_type}: {count} 个")
# ---------- 4. 数据操作 ----------
print("\n" + "="*60)
print("🔧 数据基本操作")
print("="*60)
# 裁剪数据
raw_cropped = raw.copy().crop(tmin=60, tmax=120)
print(f"裁剪后时长: {raw_cropped.times[-1] - raw_cropped.times[0]:.0f} 秒")
# 选择通道
raw_subset = raw.copy().pick([0, 1, 2, 3, 4])
print(f"选择的通道: {raw_subset.ch_names}")
# ---------- 5. 数据可视化 ----------
print("\n" + "="*60)
print("🎨 数据可视化")
print("="*60)
# 5.1 时间序列图
print("\n1️⃣ 显示时间序列图...")
raw.plot(duration=10, n_channels=10, scalings='auto', block=True,
title='原始脑电数据 - 前10个通道')
# 5.2 功率谱密度图
print("\n2️⃣ 显示功率谱密度图...")
raw.plot_psd(fmin=0.5, fmax=50, spatial_colors=True)
plt.title('功率谱密度 (PSD) - 各频率能量分布')
plt.show(block=True)
# 5.3 通道位置图
print("\n3️⃣ 显示通道位置图...")
raw.plot_sensors(show_names=True, title='电极位置分布图', block=True)
print("\n" + "="*60)
print("✅ 第1天学习完成!")
print("="*60)