非官方中文翻译 本页译自 MNE-Python 官方文档: 查看英文原文 ↗。 文档版权归 MNE Developers 所有(BSD-3-Clause)。

处理 Epoch 元数据#

本教程展示如何为 Epochs 对象添加元数据,以及如何使用 Pandas 查询字符串根据元数据属性选择和绘制 epoch。

本教程将使用一个与往常不同的数据集:Kiloword 数据集,它包含 75 名执行词汇判断(词/非词)任务的被试的平均 EEG 数据。数据以 Epochs 格式提供,每个 epoch 代表对某个不同刺激(单词)的响应。和往常一样,我们先导入所需的模块并加载数据:

# Authors: The MNE-Python contributors.
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.
import numpy as np
import pandas as pd

import mne

kiloword_data_folder = mne.datasets.kiloword.data_path()
kiloword_data_file = kiloword_data_folder / "kword_metadata-epo.fif"
epochs = mne.read_epochs(kiloword_data_file)
Reading /home/circleci/mne_data/MNE-kiloword-data/kword_metadata-epo.fif ...
Isotrak not found
    Found the data of interest:
        t =    -100.00 ...     920.00 ms
        0 CTF compensation matrices available
Adding metadata with 8 columns
960 matching events found
No baseline correction applied
0 projection items activated

查看 Epochs 元数据#

附加到 Epochs 对象的元数据以 pandas.DataFrame 的形式存储:

assert isinstance(epochs.metadata, pd.DataFrame)

每一行对应一个 epoch。列中可以包含你希望存储的关于每个 epoch 的几乎任何信息;在本例中,元数据编码了每个试次所见刺激的信息,既包括视觉词形本身的属性(例如 NumberOfLetters、VisualComplexity),也包括单词含义的属性(例如其 Concreteness)以及它在英语词汇中的常见程度(例如 WordFrequency)。以下是所有变量;请注意,在 Jupyter notebook 中查看 pandas.DataFrame 时会渲染为 HTML 表格,而不是通常的 Python 输出块:

epochs.metadata
WORD Concreteness WordFrequency OrthographicDistance NumberOfLetters BigramFrequency ConsonantVowelProportion VisualComplexity
0 film 5.450000 3.189490 1.75 4.0 343.250 0.750 55.783710
1 cent 5.900000 3.700704 1.35 4.0 546.750 0.750 63.141553
2 shot 4.600000 2.858537 1.20 4.0 484.750 0.750 64.600033
3 cold 3.700000 3.454540 1.15 4.0 1095.250 0.750 63.657457
4 main 3.000000 3.539076 1.35 4.0 686.000 0.500 68.945661
... ... ... ... ... ... ... ... ...
955 drudgery 3.473684 1.556303 2.95 8.0 486.125 0.625 69.732357
956 reversal 3.700000 1.991226 2.65 8.0 859.000 0.625 60.545879
957 billiard 5.500000 1.672098 2.90 8.0 528.875 0.625 55.838597
958 adherent 3.450000 0.698970 2.55 8.0 615.625 0.625 68.088112
959 solenoid 4.111111 0.301030 3.70 8.0 443.250 0.500 64.544507

960 rows × 8 columns



查看给定 epoch 和元数据变量的元数据值,可使用任意 Pandas 索引方法,例如 loc、iloc、at 和 iat。由于 DataFrame 的索引是整数 epoch 编号,基于名称和基于索引的选择方法在选择行时表现相似,只是基于名称的选择(使用 loc)会包含端点:

print("Name-based selection with .loc")
print(epochs.metadata.loc[2:4])

print("\nIndex-based selection with .iloc")
print(epochs.metadata.iloc[2:4])
Name-based selection with .loc
   WORD  Concreteness  ...  ConsonantVowelProportion  VisualComplexity
2  shot           4.6  ...                      0.75         64.600033
3  cold           3.7  ...                      0.75         63.657457
4  main           3.0  ...                      0.50         68.945661

[3 rows x 8 columns]

Index-based selection with .iloc
   WORD  Concreteness  ...  ConsonantVowelProportion  VisualComplexity
2  shot           4.6  ...                      0.75         64.600033
3  cold           3.7  ...                      0.75         63.657457

[2 rows x 8 columns]

修改元数据#

与任何 pandas.DataFrame 一样,你可以按需修改数据或添加列。这里我们将 NumberOfLetters 列从浮点型转换为整型,并添加一个布尔列,将变量 VisualComplexity 任意划分为高、低两组。

epochs.metadata["NumberOfLetters"] = epochs.metadata["NumberOfLetters"].map(int)
epochs.metadata["HighComplexity"] = epochs.metadata["VisualComplexity"] > 65
epochs.metadata.head()
WORD Concreteness WordFrequency OrthographicDistance NumberOfLetters BigramFrequency ConsonantVowelProportion VisualComplexity HighComplexity
0 film 5.45 3.189490 1.75 4 343.25 0.75 55.783710 False
1 cent 5.90 3.700704 1.35 4 546.75 0.75 63.141553 False
2 shot 4.60 2.858537 1.20 4 484.75 0.75 64.600033 False
3 cold 3.70 3.454540 1.15 4 1095.25 0.75 63.657457 False
4 main 3.00 3.539076 1.35 4 686.00 0.50 68.945661 True


使用元数据查询选择 Epochs#

所有 Epochs 对象都可以按事件名称、索引或切片进行子选择(参见 Subselecting epochs)。不过,带有元数据的 Epochs 对象还可以使用 Pandas 查询字符串进行查询,只需像平常传入事件名称那样传入查询字符串即可。例如:

print(epochs['WORD.str.startswith("dis")'])
<EpochsFIF | 8 events (all good), -0.1 – 0.92 s (baseline off), ~493 KiB, data loaded, with metadata,
 'district': 1
 'display': 1
 'disarray': 1
 'disaster': 1
 'disease': 1
 'discord': 1
 'disposal': 1
 'distance': 1>

该功能底层调用 pandas.DataFrame.query() 方法,因此可以查阅该方法的文档,了解如何编写查询字符串。下面是另一个示例:

print(epochs["Concreteness > 6 and WordFrequency < 1"])
<EpochsFIF | 4 events (all good), -0.1 – 0.92 s (baseline off), ~261 KiB, data loaded, with metadata,
 'lasso': 1
 'tentacle': 1
 'banjo': 1
 'corsage': 1>

另请注意,按条件名称进行的传统 epoch 子选择仍然有效;MNE-Python 会先尝试传统方法,失败后再回退到丰富的元数据查询。

epochs["solenoid"].compute_psd().plot(picks="data", exclude="bads", amplitude=False)
EEG
    Using multitaper spectrum estimation with 7 DPSS windows
Plotting power spectral density (dB=True).

Pandas 查询字符串方法的一种用途是选择特定的单词进行绘图:

words = ["typhoon", "bungalow", "colossus", "drudgery", "linguist", "solenoid"]
epochs[f"WORD in {words}"].plot(n_channels=29, events=True)
Raw plot
You seem to have overlapping epochs. Some event lines may be duplicated in the plot.
Using qt as 2D backend.

请注意,在这个数据集中,每个“条件”(也就是每个单词)只出现一次;而在 Sample 数据集中,每个条件(例如“auditory/left”、“visual/right”等)会出现数十次。因此,当你想要聚合条件名称不同但刺激属性相似的 epoch 时,Pandas 查询方法尤其有用。例如,下面我们按刺激单词的字母数对 epoch 分组,并比较每组在电极 Pz 处的平均信号:

evokeds = dict()
query = "NumberOfLetters == {}"
for n_letters in epochs.metadata["NumberOfLetters"].unique():
    evokeds[str(n_letters)] = epochs[query.format(n_letters)].average()

mne.viz.plot_compare_evokeds(evokeds, cmap=("word length", "viridis"), picks="Pz")
Pz

元数据还可用于对图像图中的 epoch 排序。例如,下面我们按单词频率对 epoch 排序,看看响应的潜伏期或强度是否存在某种模式:

sort_order = np.argsort(epochs.metadata["WordFrequency"])
epochs.plot_image(order=sort_order, picks="Pz")
Pz, µV
Not setting metadata
960 matching events found
No baseline correction applied
0 projection items activated

尽管在这个例子中没有明显的关系,但对于更直接反映刺激加工时间进程的元数据变量(例如反应时),这类分析可能很有用。

为 Epochs 对象添加元数据#

只要给 metadata 属性赋值,就可以向任何 Epochs 对象添加元数据 DataFrame(或替换现有元数据):

new_metadata = pd.DataFrame(
    data=["foo"] * len(epochs), columns=["bar"], index=range(len(epochs))
)
epochs.metadata = new_metadata
epochs.metadata.head()
Replacing existing metadata with 1 columns
bar
0 foo
1 foo
2 foo
3 foo
4 foo


将 Epochs 对象的 metadata 设置为 None,即可移除其元数据:

epochs.metadata = None
Removing existing metadata

脚本总运行时间:(0 分钟 2.275 秒)

图库由 Sphinx-Gallery 生成