在 R 中模拟具有多个条件的随机游走的离散近似

问题描述 投票:0回答:1

我正在为有两个条件的任务构建一个模拟器。在每次试验中,条件应该在

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     |

r for-loop simulation random-walk
1个回答
0
投票

本质上,最里面的循环会覆盖该行,因为两个

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)
)

在线演示

© www.soinside.com 2019 - 2024. All rights reserved.