了解PsychoPy的数据记录

时间:2015-03-31 06:56:04

标签: psychopy

我有一个测试PsychoPy Builder脚本,我用它来调查一些反直觉的行为。结构是四个例程:

"初始化",不在循环中,以下代码在"开始实验":

x = 0
y = 0
z = 0
foo = [0, 0, 0]

"一个",在一个循环中,以下代码在"结束例程":

x = x + 1
foo[0] = foo[0] + 1

thisExp.addData("x", x)
thisExp.addData("y", y)
thisExp.addData("z", z)
thisExp.addData("foo", foo)

"两个",在一个循环中,以下代码在"结束例程":

y = y + 2
foo[1] = foo[1] + 2


thisExp.addData("x", x)
thisExp.addData("y", y)
thisExp.addData("z", z)
thisExp.addData("fooY", foo[1])
thisExp.addData("foo", foo)

"三",在一个循环中,以下代码在"结束例程":

z = z + 3
foo[2] = foo[2] + 3

thisExp.addData("x", x)
thisExp.addData("y", y)
thisExp.addData("z", z)
thisExp.addData("foo", foo)

没有其他代码,没有其他组件。惯例" One"," Two"和" Three"按顺序执行五次循环。 CSV输出文件的相关列如下:

trials.thisRepN trials.thisTrialN   trials.thisN    trials.thisIndex    x   y   z   foo         fooY
0               0                   0               0                   1   2   3   [5, 10, 15] 2
1               0                   1               0                   2   4   6   [5, 10, 15] 4
2               0                   2               0                   3   6   9   [5, 10, 15] 6
3               0                   3               0                   4   8   12  [5, 10, 15] 8
4               0                   4               0                   5   10  15  [5, 10, 15] 10

这是预期的输出吗?如果是这样,为什么?请注意,各个变量x,y和z每次都在循环中显示更新的值(在循环结束时),而列表foo仅在循环迭代五次后显示最终值,但它在每一行都显示了这一点。但是调用列表中的各个元素会显示为单个变量。

这背后的逻辑和理由是什么?

有没有办法让列表输出像其他人一样执行?

有没有办法强制输出捕获/显示这些变量,就像调用addData()时一样,而不是等到循环结束?

1 个答案:

答案 0 :(得分:4)

我想我知道这里出了什么问题。这可能是因为python通过引用而不是复制来分配。这在别处详细解释,但简要说明,

original = [1, 2]
new = original  # new is simply a reference to original! It is not a copy.
new[0] = 'Oops'  # original is now ['Oops', 2] as is new (which is just a reference or pointer

在您的情况下,TrialHandler接收引用,该引用仅指向" foo"在整个实验中更新的变量。由于日志仅在实验结束时保存,因此" foo"中的所有行都被保存。现在指向" foo变量"现在保持价值[5,10,15]。

这种按引用分配可以非常漂亮和方便,但有时会像你的例子那样引起头痛。它适用于所有python mutable:列表,dicts,函数和类。但不是为了不变量,如数字,元组和字符串!这就是为什么你的脚本适用于数字但不适用于列表的原因。

有不同的解决方案。最简单的可能是用addData替换thisExp.addData("foo", tuple(foo))调用,它将可变列表转换为不可变元组。也可以做thisExp.addData("foo", [x for x in foo])。针对所有类型对象的更全面的解决方案是在实验开始时运行import copy,然后在其他代码块中添加thisExp.addData("foo", copy.copy(foo))之类的数据(如果您有一个复杂的对象,请使用{{ 1}}代替)。