分享

GazeR-基于采样点数据的注视位置和瞳孔大小数据分析开源工具包

 思影科技 2020-10-13
从视觉科学、心理语言学到市场营销和人机交互,眼球追踪在科学界广泛应用。但令人惊讶的是,到目前为止,在眼动数据的预处理步骤中几乎没有持久性和透明性,这使得许多研究的重复和再现性变得困难。为了增加可重复性性和透明性,本文的作者团队创建了一个基于R语言的被称为gazeR的眼动分析工具包,用于读取和预处理两种类型的数据注视位置数据和瞳孔大小数据。
对于注视位置数据,gazeR具有读取原始的眼动采样点数据、进行模式化的分析、将注视坐标转换为感兴趣的区域以及收集和整合数据的功能。对于来自瞳孔测量研究的数据,gazeR包具有读取和合并多个原始瞳孔数据文件的功能,去除缺失值,消除伪迹,眼睛识别和插值,进行基线校正,和合并数据的功能。该软件包是开源的,可以免费下载和安装:https://github.com/dmirman/gazer本文提供了来自两个任务的逐步的数据分析,举例说明了包的功能。该工具包在许多方面有着以往其他工具包不具有的优势,我们将在后文的解读中为大家进行强调和举例。该包的出现可以方便眼动研究人员更加了解眼动数据的处理过程以及提升在眼动研究中的可重复性。
请注意,本文的介绍基于你已经熟悉R语言的基本编写知识,不针对初学者,不是R语言的教程文件,仅针对本文所说的gazeR包。本文发表在Behavior Research Methods杂志。

背景简要介绍:
眼球追踪技术精度的不断提高以及技术成熟度的提升使其在当下已经成为一种强大且相对廉价的工具,可以收集认知过程中时间动态的高分辨率测量数据。因此,越来越多的科学家,从视觉科学、心理语言学到市场营销和人机交互,都采用了这种方法。尽管眼球追踪数据越来越多,但其处理方式存在相当大的差异性。随着对可复制性、可再现性和透明性的重视,需要跨平台、完全自由地实现眼球跟踪数据处理方面的标准实践R (R Core Team, 2019)是一种广泛使用的、免费的、跨平台的、开源的统计编程语言,它提供了满足这些需求所需的工具。在R中,很少有现成的管道来处理来自视觉世界范式和瞳孔测量法的瞳孔和注视数据,特别是包含在一个工具包中(可看表12)。为了满足这个需求,本文的研究者创建了gazeR包。gazeR包是为了方便在同一个编程环境(R)内完成从读取原始数据文件到统计分析和生成眼球跟踪数据的端到端处理。gazeR包的设计中考虑到了许多R使用者对函数的使用习惯,因此,熟悉R语言的研究者在读完本文后就可快速上手。
在作者的这篇论文中,提供了如何使用gazeR包分析实验数据的具体过程,其中主要的结果衡量是注视位置或瞳孔大小。关于分析瞳孔和注视数据的最佳实践,有几个概念或理论讨论(Mathot等人,2018;Winn, Wendt, KoelewijnKuchinsky, 2018;SalverdaTanenhaus, 2018)。本文的主要目的是说明和解释如何使用gazeR以更标准化的方式分析注视和瞳孔数据,以便研究人员可以使用它来分析自己的数据。虽然有各种各样的包和在线资源可以开始进行眼球追踪,但这些包在自由度上都受到许多限制,不能代表研究人员通常想用他们的数据做什么。第二个目标是促进可重复和透明的预处理过程,希望本包能够使研究者从使用传统的方法处理眼动数据平滑的过渡到从数据预处理到数据分析和可视化都使用代码来完成。接下来,我们先看看gazeR包的主要功能以及它和其它的眼动分析包的主要功能比较:
1 gazeR包和其他处理眼动瞳孔大小数据的包比较
从表1中可以看出,在衡量数据包的帮助文档、输入文件支持格式、支持的眼动数据组织形式、行为数据提取、眨眼检测、眨眼延长、插值算法、数据平滑、基线矫正、伪迹探测和统计时间数据这些指标的对比中,gazeR不仅具有所有这些处理功能,并且在支持文档上相对完善,并且在支持的眼动仪和数据格式上也具有极大的灵活性,结合了许多工具包的优势,相比其他工具包更有优势。

2 gazeR和其他处理注视位置的工具包的比较
从表2可以看出,gazeR相比另外一个处理注视位置数据的eyetrackingR的开源包在支持格式上更多,而比特定于眼动仪开发的两个工具包则更加灵活,对数据仪器来源没有要求。因此,可以放心的使用gazeR来整合所有的眼动数据。
 
1. 安装与下载
 GazeR旨在以一种相对原始的格式处理数据,在这种格式中,眼睛对眼球追踪器探测到的信号进行响应。这允许使用者以最大程度的兼容性来处理数据:只要文件中包含XY坐标、瞳孔大小和/或相关事件信息,任何眼球追踪器的数据都可以使用。对于本文所包含的示例,作者将讨论如何对市场上流行的商业眼球追踪器SR EyeLink收集的数据进行预处理而不需要使用DataViewerDV)。
由于GazeR是基于R语言的,因此你需要自己搭建R的编程环境。这个过程相当简单,要感谢Rstudio使得R语言的编写变得容易。在搭建好环境下,你只需要先安装好remotes包就可以安装GazeR了,代码如下:
除此以外,作为一个成熟的工具包,必然使用到其他的已经成熟的R语言包,你还需要library其他需要使用到的工具包,使用以下代码加载:
   加载没报错的话,就说明一切ok,一般来说都会没有问题的。接下来我们来看具体操作。

2. 注视数据的处理教程
作者使用了 Visual World Paradigm (VWP)范式的一个实验来说明对注视数据的处理过程。这个部分我们来看gazeR是如何从原始的眼动数据经历预处理过程、指标提取过程以及后续的统计检验的。
在典型的VWP中,被试会听到口头指令来操作或选择现实世界中的几个图像或计算机屏幕上的物体。几十年的研究表明,注视比例的时间过程,也就是在特定时间注视特定物体的概率,反映了人对该物体的心理表征的激活。图1展示了一个典型的VWP任务。在这个例子中,研究考察了语义竞争展示中包含了一个与目标对象相关的关键性干扰物(联想;例如,狗和绳;分类(例如,苹果和梨)。在一个trail中,会显示包含的目标对象图像,该图像的语义竞争图像(分类或联想相关的图像,如图1中的狗和绳子是联想相关),以及两个不相关的干扰物。指标是在每个时间点对特定对象的注视概率(即注视比例)(1右面板显示的示例数据)
1 VWP范式说明
现在我们来看处理过程,主要分为以下四个步骤:
(1)读取数据;
(2)消除track loss的数据;
(3)指定感兴趣的区域;
(4)注视数据的时间过程分析(可选);
首先,为了处理由EyeLink系统生成的EDF文件,您需要首先安装由SR-Research提供的EDFAPI,这是免费的,使用edfR包即可(Hubbard &(von der Malsburg, 2015) gazeR使用它读取EDF文件。为了读取EDF文件,必须指定两个文件夹路径一个路径是EDF文件所在的位置,另一个路径是原始CSV文件应该保存的位置。
代码的第一行中填入你本地的edf文件保存的路径,第二行填入你的csv文件需要保存到的路径。第三行不需要修改,直接按图中所示输入即可。这样,你的数据就被导入到file_list_edf 这个变量中了。
指定文件夹路径后,可以调用parse_edf函数。这个函数从EDF文件导入示例数据。类型参数必须指定为pupilvwp,取决于你所使用的实验设计。parse_edf函数将来自原始EDF文件的示例数据和原始数据合并起来,并将它们转换为适合于用gazeR进行预处理的格式。具体来说,该函数将时间以毫秒为单位,添加被试id、试验和trial信息,并计算单眼变量的平均xy注视坐标和直径值(左眼、右眼或双眼的平均值)parse_edf函数从使用者指定的目录中的每个EDF文件生成一个CSV文件。merge_gazer_files函数可以整合这些新的CSV数据文件存储在directory_csv_ from_edf_conversion所指定的路径中。对于用parse_edf处理的文件,需要将filetype参数设置为edf。代码实现为下图:
在导入数据后,需要注意的是当使用原始EDF文件时,相关的行为信息变量(例如,条件变量,RTs,和准确率)通常在眼动仪记录的数据之外。要在一个完整的表中显示相关的试验变量,可以运行find_messages_edf函数,该函数将从每个EDF文件生成一个CSV文件。为了使函数正常工作,使用者必须指定特定的变量名(varnames参数)和需要替换的变量名模式(patterns参数)。因为,SR会在行为变量前添加一个TRIALVAR标记。函数如下:

运行find_messages_edf函数后,可以使用merge_gazer_files函数合并每个被试的行为数据。然后,行为数据可以加入到眼动数据中。
在合并了数据后,你可以使用如下函数来查看你的csv文件,应如下图中的表格所示:

作者这里给出的样例数据,如果你没有自己的数据,可以使用作者给出的样例数据,保存在gazer包中,使用它来练习。
对于这个示例数据集,gaze数据包含从原始EDF文件中提取的眼球跟踪变量和特定于实验的值(不同对象的位置、试验条件、被试的正确率和反应时)。使用summary函数来概览这个表格:

接下来是处理track loss的数据。可以使用每个采样的XY坐标相对于屏幕的大小(分辨率)来确定。get_trackloss函数可以确定每个trail中被试相对屏幕的开/关状态,计算试验中每个被试的track loss比例,这个filter过程可由使用自己定义阈值(也可以通过设置阈值为1.0来省略这个过程)。在这个函数中,需要定义scree_size函数,来说明屏幕的分辨率大小,以用来确定每个trail采样过程中的XY坐标是否属于track loss数据。
      在处理了track loss数据后,我们就应该对AOI(area of interesting,感兴趣区)进行整合了。下面的预处理假设感兴趣的区域(物体的位置)是静态的,在导入的眼动数据中包括了指示每次试验中每个物体位置的列。在这个例子中,对象总是出现在屏幕的四个角上,但是哪个对象出现在哪个角是随机的。这四个可能的图像位置被标记为image1image2image3image4TargetLoc变量标识哪些位置是目标对象,而CompPort变量标识哪些位置是关键语义相关的竞争图像。注视位置以(X,Y)坐标记录。为了确定哪些(如果有的话)物体被注视,首先确定目标和竞争者图像的位置,然后使用注视坐标来确定被注视的图像位置(如果有的话),然后比较注视位置与目标和竞争者的位置。如果注视位置已经按照感兴趣的区域进行了编码(许多实验程序在收集数据时动态地进行编码),那么可以跳过这一步。这一步使用assign_gaze函数完成,assign_aoi函数将根据屏幕坐标(默认为1024x768屏幕角上的400x300矩形)将注视位置匹配到感兴趣的编号区域(AOI),需要将其匹配到图像位置标签上。

接下来,通过匹配目标和竞争图像位置的AOI代码来确定被注视的对象,这个代码中作者定义了三个AOI,目标对象AOITarg,竞争图像AOIComp,不相关的其他图片为一个AOI,名字为Unrelated。对于无关数据,作者使用了&的逻辑式来表达,不属于前两个AOI也不是0Na值的数据编入这个UnrelatedAOI中。


在对AOI进行整理后,之后的数据组织和汇总的细节取决于具体研究的设计和假设,这个步骤具有相当大的灵活性。对于本文的例子,凝视位置需要从单独的列收集到一个列中,NA值需要重新编码为无凝视位置。作者使用了如下函数来整理表格,其中%>%为管道函数,用来传递参数给下一个函数的第一个参数位置,gather函数的目的是将不同的变量整理为一个新的变量,作者把三个独立的AOIAOI(area of interesting,感兴趣区)变量整理为一个新的变量“object”,所有的值编入了fix变量。然后使用mutate函数增加了一个新的变量为Fix,这个新的变量由原表中的fix函数编码里面的na值为FALSE生成。


如果你愿意,可以使用downsample_gaze函数将数据向下采样到更大的时间采样间隔中。这个函数将样本集整合为一个时间序列,该时间序列由使用者指定大小的标准化时间间隔组成(默认为50ms)。此外,它还删除不再需要的列。使用者需要指定列(即明确aggvars参数),它定义了整合的级别(例如,单个trial)
函数使用如下,使用downsample_gaze函数,指定数据后,设定bin的长度,默认50ms这里的bin其实就是说你把的采样数据按照多大的时间窗口来重新分割取值),然后设置aggvars函数,这里的意思是说,对于每个被试,每个条件的每个trial采集的时间数据进行降采样,得到新的变量timebins,其中targetobject给出AOI信息。

在预处理的最后阶段,可以去除误差和练习时的试验,并限制时间窗口,使数据做好整合准备。对于本例,作者按被试、条件和对象类型对试验进行分组,以计算每个单元格中有效试验的数量。然后按时间点分组,计算每个时间点的物体注视次数和平均注视比例;也就是固定的时间过程。这些是根据具体情况进行分析的过程,每个使用者可以根据自己的实际情况来完成。在下面的图片中,可以到作者首先筛选出正确的,condition不为练习的数据,然后使用grouo_by函数按照被试、conditionobjecttimebins对数据进行分组整理,并使用summarize函数获得Fix的均值数据。作者之所以下面对Unrelated的数据除2是因为这个里面包含的是两张图片,被放在一个AOI中了。

将注视数据分配给对象类型并转换为时间窗口数据之后,就可以进行可视化和统计分析了。图2为各类型目标的固定比例时间的时程分析图。

作者使用了ggplot来绘图,使用condition作为分割图形的依据,使用每个时间窗口的均值来作为y轴的数据,x为每个trail的时间点。使用颜色来区分观看的对象:

2 3500ms中,被试在不同的语义关联条件下对不同图片对象的注视比例
以上就一个完整的分析过程了,可以看出gazeR的分析流程很快速。后续其他分析就是使用者根据自己的统计需求来进行定义了。非常灵活,接下来我们来看瞳孔数据的处理。

如果您对眼动数据处理感兴趣,可浏览思影科技课程及服务(可添加微信号siyingyxf18983979082进行咨询):

第七届眼动数据处理班(南京,7.26-30)

思影科技眼动数据处理服务

3. 瞳孔数据的处理教程
瞳孔测量与认知关联研究已经越来越受到研究者的欢迎。因为瞳孔大小的变化与更高层次的处理有关。根据最近的PubMed搜索(见图3),自半个多世纪前第一次现代繁荣以来,使用瞳孔测量法的研究数量呈指数级增长。原因很简单:瞳孔大小已经被证明是一个可靠和有效的认知努力或觉醒指数,在许多领域,包括单词识别,正常和受损的听觉感知,语义认知,注意力分配,工作记忆负荷,面部感知,和一般认知加工。虽然在R中有许多很好的开源程序可以用来分析瞳孔数据,但是没有很多演示如何从原始数据到完全预处理数据的支持性文档。Winn等人(2018)最近的一项方法综述并阐明了眨眼检测、插值和滤波等一般原理。gazeR包包括实现这些步骤的函数,在这里作者演示了它们的用法。为了演示对瞳孔数据的分析,本文将使用一个包含词汇决策任务数据的示例数据集。在这个演练中,被试(N=3)判断词汇真假(即,这是一个单词还是不是一个单词?)并记录瞳孔直径。使用了手写体词汇刺激和印刷体刺激,因为手写体的刺激是不可分割的,并且可能是模糊的,本文预测识别草书的刺激将需要比印刷的单词更多的努力,导致更大的瞳孔扩张。

3 Pubmed上的瞳孔数据研究增长

瞳孔数据的分析流程可以总结如下:
(1)读取数据
(2)De-blinking(对眨眼的处理)
延长眨眼
平滑和插值
(3)基线校正
(4)Re-scaling(单位标准化)
(5)伪迹剔除及处理;缺失的数据,不太可能的中位数绝对偏差(MAD)
(6)事件时间对齐
(7)时间序列数据整理
首先来看读取数据。对于你自己的数据(包括许多单独的文件),函数parse_edf将生成基于EDF数据的gazeR所需的必要文件。对于非edf文件,可以使用make_gazer函数使数据适合于gazeR。这将返回一个数据框,其中列名更改为:subjecttrialblinkxypuilptimemessage。在使用parse_edf函数(上面解释过)将每个EDF文件保存为CSV之后,可以调用merge_gazer_files函数来整合所有瞳孔文件。

这里的代码和导入采样点的注视数据时的内容是一样的,如果你忘了他们的含义,请往上翻看。同样的,你可以使用find_messages_edf函数来加入你的行为学数据。用法和前文中一样。

由于数据大小的处理限制,例子中使用的数据文件包括来自少数被试的数据以及他们所有的行为数据。可以使用示例数据对parse_edfmerge_gazer_filesfind_messages_edf 函数进行测试,这些示例数据可从开放科学框架(OSF)下载:https:// osf.io/fzu38/

作者这里导入了puilp_sample_files_edf这个数据,从gazer包里导入的。你可以自己去osf网址下载edf数据,然后来进行练习。
合并之后,behave_pupil函数将从示例报告中挑选重要的行为数据。当omiterror =TRUE时,函数将返回一个没有错误的数据框;omiterror =FALSE时,函数将返回一个有错误的数据框进行精度分析。需要在behave_col names参数中指定与你的实验相关的列。此函数不能消除异常值;必须使用你自己偏好的方法(没有一种剔除异常值的方法是完美的,所以需要你自己来选择)Granges(2015) trimr包实现了多个离群值排除的标准方法(https://github.com/ JimGrange/trimr)。整体实验和被试的准确率可以合并到瞳孔数据表中。

在本文的示例数据中,去除被试准确率低于75%的被试和项目准确率低于60%的数据。当参数omiterror =FALSE时,使用上面生成的dataframe来计算。然后,合并准确率变量和subject变量到瞳孔文件。我们现在限制预处理来验证试验,通过删除练习模块,不正确的反应,非单词的条件,准确率低于75%的被试,以及准确率低于60%的项目。

熟练使用filter函数可以快速根据条件筛选需要的数据,使用arrange函数可以进行排序。
接下来是De-blinking瞳孔数据的一个主要伪影来自于眨眼。当眼睛眨眼时,瞳孔会因为被眼皮越来越遮挡而暂时变小,这使得计算瞳孔中心变得困难。眼球追踪器将其解释为瞳孔位置的快速变化,并可能错误地将其归类为扫视。此外,瞳孔大小的估计会随着瞳孔在相机图像中所占的比例的减少而迅速减小。这个过程在眼睛睁开时发生反向(实际上更低),因此眨眼的两侧总是会出现假的扫视和/或瞳孔大小的假变化。偶尔还会有一些额外的伪影,比如眨眼前后的短暂注视。因此,建议对数据进行de-blinking包括识别眨眼,删除眨眼数据,在眨眼之前和之后删除数据,然后在被删除的时间段内插值数据。gazeR中,当使用saccades包导入原始edf时,眨眼被自动识别(von der Malsburg, 2019)。对于其他格式的数据,可以使用detect_blink函数来识别闪烁。saccades软件包中的眨眼检测使用了Engbert & Kliegl(2003)的基于速度的算法。眨眼事件被认为是任何看起来像注视的对象,但是它的离散度比典型的注视要低得多。在saccades包中,眨眼是一个色散小于色散的中值减去色散的中值绝对偏差的四倍的事件,且仅当这是水平和垂直色散的情况。在对瞳孔数据进行预处理时,还有一件重要的事情,那就是决定在眨眼前后要去除多少数据点。一般建议消除眨眼前后的100ms数据。有几种处理眨眼的方法(参见Hershman, Henik & Cohen, 2018)。一种方法是在试验中消除所有眨眼现象。通常不建议这样做,因为这样会删除太多数据,导致数据损耗。一种更容易接受的方法,也是在gazeR中实现的方法,是延长眨眼周围的时间窗,这样插值在眨眼前100-200毫秒开始,眨眼后继续(Nystrom, Hooge & Andersson, 2016;Satterthwaite等,2007)。延长眨眼周围的时间窗可以消除因眼皮的关闭和打开而产生的假样本。extend_blinks函数使用fillback参数指定眨眼前应该向后扩展的时间,fillforward参数指定眨眼后应该向后扩展的时间。还需要制定hz参数,此函数对不同采样率是稳健的。在本次实验中,采样频率为250Hz(4 ms采样一次)的眼动跟踪器,眨眼时间前后延长100 ms。函数实现如下:

4 线性插值的效果图 红线为线性插值,绿色为线性滤波,蓝色为原始数据

5 非线性插值的效果图 红色为立方插值、绿色为立方滤波,蓝色为原始数据
接下来是对数据的平衡和滤波。瞳孔数据可能是非常嘈杂的。为了去除一些这种噪声,通常要进行滤波和插值。在gazeR中,这一步使用smooth_interpolate_pupil函数就可以完成。第一个参数使用者可以选择先用n移动平均数平滑数据,然后插值(步长)。根据所选择的方法,步骤的顺序可以产生不同的影响(见图4和图5);如果应用三次样条插值,一般建议在插值前进行平滑。gazeR包目前实现了两种常用的平滑瞳孔数据的方法:n点移动平均和汉宁窗方法(作者计划在包的未来更新中包括更多的平滑选项)。要平滑数据,必须指定包含瞳孔信息和移动平均窗口(在样本中)大小的列。在这个例子中,作者使用5点移动平均(n=5),在250hz的采样率下,相当于1250ms的移动平均。
由于眨眼或眼动器故障而造成的数据缺失需要进行插值。smooth_interpolate_pupil函数搜索数据,并利用线性插值的方法,从相关样本中重新构建每个试验的平滑瞳孔大小或立方样条插值函数(Mathot, 2018)。考虑到眨眼时间短,眨眼速度相对较低,线性插值和立方插值的选择最终影响可以忽略不计。如果extendblinks= FALSE,带有blinks的样本将被转换为NAs,然后进行插值。这个函数返回一个tibble对象,该对象带有一个名为pup_interp的列,其中包含移动平均瞳孔数据的内插值。这里也有表示要进行插值的最大间隙数的选项。这需要指定眼动仪的采样率(hz)。需要注意的是,如果不需要新的extendblink列,那么extendblinks参数应该设置为FALSE。如果需要扩展extendblink列,则extendblink参数应该为true。值得注意的是,在示例报告中,SR只扩展blink列,而没有在眨眼期间对NA设置瞳孔大小估计数。对于本例,将把extendblinks设置为TRUE并使用线性插值。你可以通过将type参数更改为cubic来使用cubic插值。


在做完降噪后,需要进行基线校正。为了控制由非任务相关(紧张)唤醒状态引起的整体瞳孔大小的变化,通常使用基线校正。两种最流行的基线矫正方法是减法矫正(瞳孔大小-基线)和分离矫正(瞳孔大小变化-基线/基线)。减法基线校正在文献中更为常见,这种做法反映了与基线大小无关的瞳孔反应的线性。baseline_correction_pupil函数查找每个试验在指定基线期间的中位数瞳孔大小,并在默认情况下执行减法基线校正。通过将baseline_method参数更改为div,您将获得基线的比例变化。在本例中,对任意单位(瞳孔colname="pup_interp")的瞳孔大小应用减法基线校正,对mmz-score的瞳孔大小也可以进行同样的校正。如果事件是固定的或静态的,则可以使用baseline_correction_pupil函数的baseline_window参数来设置基线时间窗口。


如果实验中的事件是动态发生的,则可以使用baseline_correction_pupil_msg函数。此函数接受一个使用者指定的、紧接刺激开始消息之前的基线周期。在下例中,将baseline_dur参数设置为100 ms,将event参数设置为target。这将计算出目标发生前100毫秒的中位基线值。基线持续时间的选择似乎在很大程度上无关紧要,对实际数据影响不大(Winn等人,2018)

在做完基线校正后,需要做re-scaling ,进行单位标准化。到目前为止,分析步骤使用的是任意瞳孔单位。建议将其转化为标准化单位,以便在个体之间进行比较。在之前的研究中已经使用了许多不同的单位,如z scoresmm的绝对变化,相对基线的比例变化,相对峰值的比例变化,以及光反射引起的瞳孔反应动态范围的绝对变化等。为了将任意瞳孔大小转换为mm,作者用人工瞳孔(5 mm)进行了一个短实验,测量了比例因子,并计算了任意单位的平均瞳孔大小。在一个固定的相机到瞳孔的距离为90厘米时,5mm瞳孔被编码为5570个任意像素单位。将这些信息输入到下面的公式中,可以将任意单位转换为mm。具体来说,将经过平滑的瞳孔大小值乘以5/5570,将其缩放为mm单位,代码如下:

当然,你也可以转换为z分数,代码如下:

关于group_by函数和mutate函数前文已经描述过了,不再赘述。在单位标准化以后,需要去除伪迹。第一个就是对缺失值的处理,count_missing_pupil函数将删除丢失大量数据的被试和项目数据。Winn等人(2018)建议,合理的阈值为20%但是在实际实验中,使用者可以自己来定义。对于本例,我们将missingthresh参数设置为0.2,将瞳孔参数设置为数据集中原始的、非插值的瞳孔数据列。count_missing_pupil函数返回被排除在分析之外的被试和项目的百分比。

对缺失值进行排除后,接下来是对数据的异常值进行处理。把太小或太大的不太可能的瞳孔值从数据中删除。Mathot(2018)建议不要基于与被试无关的固定标准(例如,高于或低于SD界限或特定的上下瞳孔界限)删除数据。这是由于实验中瞳孔大小的固有异质性造成的。相反,Mathot(2018)建议通过视觉检查来确定不太可能的瞳孔值。这可以使用简单的直方图来绘制瞳孔测量数据。根据下面的直方图,移除小于2500和大于5000的瞳孔尺寸似乎是合理的。图6

6 瞳孔大小的频数分布图

画图代码如下:

使用ggplot画图,x为保存瞳孔数据大小的列,pup_interp,然后纵坐标为count该值出现的频次,所以是频数分布直方图。使用geom_vline添加x25005000的线,说明这两条线以外的数据出现频次太低,可能为异常值。使用下面的filter函数排除。
在插值之后,执行第二次滤波以确保数据不受快速瞳孔大小干扰是一个好方法。这些伪迹可以使用中值绝对偏差来检测,这是比传统的可变性度量更优的方法(例如,标准偏差;Hampel, 1974;Kret & Sjak-Shie, 2018)。对于每个时间点,speed_pupil函数计算归一化扩张速度,即样本间瞳孔大小的绝对变化除以样本间的时间间隔。为了检测异常值,MAD是由膨胀速度变量乘以一个常数计算出来的(在本例中是16,这是Kret & Sjak-Shie, 2018年使用的值)常数控制灵敏度阈值:常数越高,需要标记去除的值就越极端。利用calc_mad函数将MAD加到中值膨胀速度变量中;超过此阈值的值将被删除。代码实现如下:


在大多数心理学实验中,每次试验都包括几个事件。在示例实验中,每个试验都以固定屏幕(屏幕中央的小十字)开始,每个试次开始后1s感兴趣的刺激物出现在屏幕上。这些事件记录在数据文件中:感兴趣的刺激物的开始由试验数据中的“target”表示。我们可以使用这个信息来调整数据,使时间=0对应于stimulus开始而不是trail开始(trail 往往是相对于一个组合的刺激组来说的,而你真正感兴趣的是刺激对象,即stimulus) onset_pupil 函数使用三个参数执行这种对齐:time column, sample message column, and the event of interest (这个示例中的“target”变量)。在下面的输出中,我们可以看到我们的实验现在从当刺激物显示在屏幕上时的0时开始:

在上面的代码中,作者先使用group_by函数针对被试和trail进行数据分组,然后使用mutate增加新的时间线数据列,命名为time_zero,然后使用ungroup函数取消上面的分组,进一步对数据进行filter,删除time_zero列中小于等于-100和大于等于2500的数据,最后选择需要用的数据赋值为新的变量baseline_pupil_onset
到这里,数据的预处理过程基本完成。接下来是数据处理,作者这里仍旧是时间序列过程数据处理为例。如果我们以相对较高的采样频率(例如,本例中为250Hz)记录数据,则将数据整合到比采样率稍大的时间窗中可能会有用(使用者可以指定要使用的时间窗口大小)downsample_gaze函数将把样本集整合为一个时间序列,该时间序列由标准化的时间窗口组成,当类型参数设置为瞳孔时,这些窗口的大小由使用者为瞳孔数据指定。此外,它将删除不再需要的列。使用者需要指定列名的向量(aggvars),它定义了整合的级别(例如,单个trail级别),并且应该在设置完成后保留。这就产生了每个被试的平均基线校正瞳孔直径,条件和时间窗这么多列数据。如果您想保持原始数据,您可以跳过这一部分。这个函数返回一个tibble,其中添加了一个名为timebins的列,可以用于整合时间序列数据(例如,计算每个timebin中的平均瞳孔大小)。具体代码如下:


经过基线校正和伪迹剔除后,可以进行可视化和统计分析(见图7)gazeR生成的预处理数据具有高度的灵活性,可以兼容不同的可视化策略。

7 瞳孔大小的时程数据可视化 红色手写文字,绿色印刷体文字

以上就是作者带我们对眼动的采样点数据进行基于注视的分析和基于瞳孔大小的分析的固有流程。至于之后的更加灵活的统计分析,则需要使用者自己来进行了,gazeR包产生的数据的格式是灵活的,兼容各种统计建模策略。例如,各种曲线拟合策略,如增长曲线分析、通用可加性模型和/或功能数据分析(Jackson & Sirois, 2009;Mirman, 2014;Seedorff, OlesonMcMurray, 2018;van Rij等,2019)。这些都需要使用者根据自己的需求来进行。
对于那些对增长曲线建模(也翻译为生长曲线模型,注释:Growth curve models是预测事件的一组观测数据随时间的变化符合生长曲线的规律,以生长曲线模型进行预测的方法。一般来说,事物总是经过发生、发展、成熟三个阶段,而每一个阶段的发展速度各不相同。通常在发生阶段,变化速度较为缓慢;在发展阶段,变化速度加快;在成熟阶段,变化速度又趋缓慢,按上述三个阶段发展规律得到的变化曲线称为生长曲线)感兴趣的人,gazeR软件包包含了一个辅助函数(code_poly),以促进使用正交多项式进行增长曲线分析(GCA) (Mirman, 2014)code_poly函数使用你的时间列,并添加时间的多项式变换到使用者指定的顺序(见图8)。多项式变换可以是自然的或正交的;正交设计可能是更有用的,因为它使时间项不相关,并将它们缩放到相同的范围(关于自然多项式与正交多项式的讨论见Mirman, 2014)

code_poly这个函数只需要你输入data数据,设定好preditctor参数为你的时间所在的那列(这里是time列),选择多项式的项数,就会帮助你生成一个新的用于进行增长曲线分析的表格。这个包还包含一个函数(get_ranef)从增长曲线中提取随机效应模型的格式,方便量化个体差异(Mirman, 2014,7)和一个函数为线性混合效应模型估计pvalues正常使用和/Kenward-Roger近似(get_pvalues)

8 VWP范式数据进行的一个四项式的多项正交的增长曲线分析模型
 
总结:
虽然有许多可行的解决方案可以处理眼动数据,但并不是所有的都适合研究目的,当前的处理方法主要存在以下一些问题:
① 全图形界面很少提供有关基础数据分析的信息,而且很难再现。
② 文件格式有时是专有的和无文档记录的,缺乏复制所需的详细注释。
③ 算法的源代码和描述并不总是用户可以访问的。
④ 有些实现依赖于昂贵的专有软件。
当下的研究社区越来越强调可重复性和开源,需要完全开放的解决方案,有可以直接操作和注释代码、数据和参数,以便其他人可以复制或批评这些方法。本文总结并演示了用R编写的免费开源包gazeR的功能。介绍了对采样点数据的注视位置和瞳孔大小数据进行预处理并使其适合分析所需的重要函数。这为预处理原始眼球追踪数据提供了一种通用的、可复制的、透明的方法。如果你对gazeR包感兴趣,一定访问他们的git主页,在那里有更详细的tutorial

GazeR: A Package for Processing Gaze Position and Pupil Size Data


如需原文及补充材料请加思影科技微信:siyingyxf 或者18983979082(杨晓飞)获取,如对思影课程感兴趣也可加此微信号咨询。觉得有帮助,给个转发,以及右下角点击一下在看,是对思影科技莫大的支持。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多