我想模拟反应时间和准确度,并且它们之间具有一定的相关性。
这是我的第一个猜测:
n <- 2000
RTs <- brms::rshifted_lnorm(n, meanlog = log(1.3), sdlog = 0.1, shift = 0.5)
acc <- sapply(RTs,
FUN = function(x){
rbinom(
n = 1,
# multiplying by 0.3 should give me a correlation around 0.3... am I right?
prob = boot::inv.logit(x * 0.3),
size = 1
)
}
)
cor(RTs, acc)
但是,所得相关性约为 0,而不是 0.3 左右。
我做错了什么?
我看过这个答案:相关校准类别和连续数据的模拟 但它模拟分类(可以转换为二项式数据)和高斯分布。
这是一个通过保留相关性进行模拟的简单解决方案。我们需要做的就是以受控方式生成二进制变量 (
acc
)(给定生成的 RT
值):
如果一个变量中越来越多的高值对应于另一个变量的高值,并且类似地对应于低值,则两个随机向量之间的相关性可以增加。
以下函数
gen.correlated.binary.data()
从要生成的目标向量 acc
中的少量 1 开始,并逐渐增加对应于变量 RT
的高值的 1 的数量(通过排序确保)。
这保持
RT
向量不变,但逐渐增加变量之间的相关性。现在,一旦达到所需的相关值就停止 - 这将在 acc
向量中创建所需的排序和比例。
最后,通过保留对应关系(从而保持相关常数)来对向量进行打乱,以生成随机
acc
向量。
gen.correlated.binary.data <- function(x, r) {
n <- length(x)
xs <- sort(x)
ys <- c(rep(0, n-1), 1)
rc <- cor(xs, ys)
i <- n
while ((rc < r) & (i > 1)) { # match sorted x with sorted y
ys[i] <- 1
i <- i - 1
rc <- cor(xs, ys)
}
ix <- sample(1:n, n, replace=FALSE)
x <- xs[ix] # shuffle
y <- ys[ix] # shuffle
return(list(x=x, y=y))
}
现在,从
RT
向量开始并生成 acc
向量:
set.seed(1)
n <- 2000
RTs <- brms::rshifted_lnorm(n, meanlog = log(1.3), sdlog = 0.1, shift = 0.5)
res <- gen.correlated.binary.data(RTs, 0.3)
RTs <- res$x
acc <- res$y
RTs
# [1] 1.804578 2.025394 1.750515 1.611236 1.791022 1.910226 1.714558 1.667378 1.658610
# ...
acc
# [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
# ...
cor(RTs, acc)
# [1] 0.3035055
下图显示了生成的变量值的分布以及相关性和拟合线。
下一个动画显示了如何修改
acc
向量来实现相关性(这次是通过逐渐增加相关性来实现0.5
),给定 RT
向量:
请注意,
RT
向量以及RT
的分布是固定的,只有acc
分布发生变化,从而相关性增加。