我正在为有两个条件的任务构建一个模拟器。在每次试验中,条件应该在
nCond
的两个水平和其他变量的相应指数之间来回切换。例如,试验 1 的刺激应为“R”,pi 值为 0.75,难度为“简单”diff
。试验二应具有 stim
“L”、pi 为 0.65、diff
为“Hard”,试验三应返回到镜像试验 1,但最终 RT 略有不同。
相反,每个试验的条件为 2,刺激为“L”,以及相同的 pi/mean_a/a_s/etc。我确信这可能是关于
mycond
索引的第二个循环的一个小问题,但我不太清楚如何修复它。
非常感谢任何帮助!
#Set a seed
set.seed(2024)
#Variable declaration-------------
nConds <- 2 #Number of conditions
stim <- c("R", "L") #Stimulus labels
pi <- c(.75, .65) #Probability of step (+1) for random walk; 1-pi will be the probability of stepping -1
diff <- c("Easy", "Hard") #Difficulty label for the condition
mean_a <- c(40, 40) #Mean upper bound for each condition
a_s <- c(0, 0) #Variability in upper bound for each condition
zp=c(.5, .5) #Multiplier of a for starting point for condition (Z = a*zp)
zp_s=c(0, 0) #Variability for starting point multiplier
Nsubs=1 #Number of subjects
Trials_per_cond=100 #Number of trials per condition
timeout=500 #Timeout parameter for the random walk
#Create an empty dataframe for storing responses
mydata=data.frame("Sub"=rep(1:1, each=100), "Trial"=1:100, "RESPONSE"=NA, "RT"=NA)
for (myperson in unique(Nsubs)){
for (mycond in 1:nConds){
condpi=pi[mycond]
cond_a=mean_a[mycond]
cond_a_s=a_s[mycond]
cond_zp=zp[mycond]
cond_zp_s=zp_s[mycond]
cond_stim=stim[mycond]
cond_diff=diff[mycond]
for (i in 1:Trials_per_cond){
mytrial=i
trial_a=rnorm(1, mean=cond_a, sd=cond_a_s)
trial_Z=rnorm(1, mean=trial_a*cond_zp, sd=cond_zp_s)
trial_Pi=rnorm(1, mean=condpi, sd=0)
#Begin setup for random walk
time=0
curpointer=trial_Z
#Conduct random walk
while (time < timeout){
time=time+1
curpointer=curpointer+sample(c(-1, 1), size=1, prob = c(1-trial_Pi, trial_Pi))
if (curpointer >= trial_a) {
myresponse="1"
break
}
else if (curpointer <= 0){
myresponse="0"
break
}
}
myRT=abs(time)
#Save the parameters to the respective trial in the dataframe
mydata[mydata$Sub==myperson & mydata$Trial==mytrial,"RESPONSE"]=myresponse
mydata[mydata$Sub==myperson & mydata$Trial==mytrial, "RT"]=myRT
mydata[mydata$Sub==myperson & mydata$Trial==mytrial, "Condition"]=mycond
mydata[mydata$Sub==myperson & mydata$Trial==mytrial, "Stimulus"]=cond_stim
}
}
}
现在茶几看起来像这样:
mydata
|sub|Trial|RESPONSE|RT |Condition|Stimulus|
|1 |1 | 1 |100 | 2 | L |
|1 |2 | 1 |130 | 2 | L |
|1 |3 | 1 |98 | 2 | L |
.....
|1 |98 | 1 |65 | 2 | L |
|1 |99 | 1 |120 | 2 | L |
|1 |100 | 1 |100 | 2 | L |
它应该看起来像这样:
mydata
|sub|Trial|RESPONSE|RT |Condition|Stimulus|
|1 |1 | 1 |102 | 1 | R |
|1 |2 | 1 |111 | 2 | L |
|1 |3 | 1 |65 | 1 | R |
.....
|1 |98 | 1 |98 | 1 | R |
|1 |99 | 1 |120 | 2 | L |
|1 |100 | 1 |100 | 1 | R |
本质上,最里面的循环会覆盖该行,因为两个
mycond
迭代器共享相同的 Sub
和 Trial
条件。考虑添加 Condition
作为空数据框中的当前列并且也在逻辑条件下:
#Create an empty dataframe for storing responses
mydata = data.frame(
"Sub"=rep(1:1, each=100), "Trial"=1:100, "Condition"=rep(1:2, 50)
)
...
#Save the parameters to the respective trial in the dataframe
row_filter <- mydata$Sub==myperson & mydata$Trial==mytrial & mydata$Condition==mycond
mydata[row_filter, "RESPONSE"] = myresponse
mydata[row_filter, "RT"] = myRT
mydata[row_filter, "Stimulus"] = cond_stim
顺便说一下,考虑一种更实用的迭代赋值形式。由于您是按元素跨行运行,因此请使用
mapply
并避免嵌套 for
循环:
run_walk <- function(mytrial, mycond) {
condpi=pi[mycond]
cond_a=mean_a[mycond]
cond_a_s=a_s[mycond]
cond_zp=zp[mycond]
cond_zp_s=zp_s[mycond]
cond_stim=stim[mycond]
cond_diff=diff[mycond]
trial_a=rnorm(1, mean=cond_a, sd=cond_a_s)
trial_Z=rnorm(1, mean=trial_a*cond_zp, sd=cond_zp_s)
trial_Pi=rnorm(1, mean=condpi, sd=0)
#Begin setup for random walk
time=0
curpointer=trial_Z
#Conduct random walk
while (time < timeout){
time=time+1
curpointer=curpointer+sample(c(-1, 1), size=1, prob = c(1-trial_Pi, trial_Pi))
if (curpointer >= trial_a) {
myresponse="1"
break
}
else if (curpointer <= 0){
myresponse="0"
break
}
}
return(
c(RESPONSE=myresponse, RT=abs(time), STIMULIS=cond_stim)
)
}
# CREATE EMPTY DATA FRAME
mydata2 <- data.frame(
Sub = rep(1:1, each=100), Trial = 1:100, Condition = rep(1:2, 50)
)
# ASSIGN TRANSPOSED MATRIX VALUES TO COLUMNS
mydata2[,c("RESPONSE", "RT", "STIMULIS")] <- with(
mydata2,
t(mapply(run_walk, Trial, Condition))
)
# CONVERT SOME COLUMNS TO INTEGER FROM FULL CHARACTER MATRIX
mydata2 <- transform(
mydata2,
RESPONSE = as.integer(RESPONSE),
RT = as.integer(RT)
)