提问人:Adam9 提问时间:10/30/2023 最后编辑:Adam9 更新时间:11/1/2023 访问量:78
如何在 R 中排列几对变量之间的相关性?
How to permute correlations between several pairs of variables in R?
问:
我想计算来自两个数据帧的变量对之间的相关性,最好使用 cor.test,这样我就可以使用估计值或统计量来比较 p 值。我的真实数据(而不是练习虚拟数据)在 df1 中有 20 个样本和 40 个变量,在 df2 中有 20 个样本和 345 个变量。
他们研究两个变量之间的互换相关性的一些示例使用了 for 循环、https://bookdown.org/curleyjp0/psy317l_guides5/permutation-testing.html#correlation-coefficient-permutation-tests 和 https://dgarcia-eu.github.io/SocialDataScience/5_SocialNetworkPhenomena/056_PermutationTests/PermutationTests,如果只有两个变量/向量,则有效。
我尝试使用 foreach 将我的每个 y 变量在 df2 中置换 1,000 次,然后通过查看置换统计量 >= 原始统计量 / 排列数的次数来计算 p 值。我一直在练习 10 种排列和一个较小的数据集,看看我是否可以让我的代码正常工作
df <- as.data.frame(matrix(round(runif(n=12*12, min=1, max=20), 0), ncol=12))
colnames(df) <- paste0("a", ncol(df))
df2 <- as.data.frame(matrix(round(runif(n=12*20, min=1, max=20), 0), ncol=20))
colnames(df2) <- paste("b", ncol(df2) )
comp <- expand.grid(colnames(df1), colnames(df2))
res <- foreach(i=1:nrow(comp), .combine=rbind, .packages=c("magrittr", "dplyr")) %dopar% {
perm <- \(){
N <- 10
samp <- sample(nrow(df2))
cor.test(df[, comp[i,1]], df2[samp, comp[i,2]], method="spearman", exact=FALSE)[c("estimate")]
}
perm_stat <- replicate(N, perm())
orig_stat <- cor.test(df[, comp[i,1]], df2[, comp[i,2]], method="spearman", exact=FALSE)[c("estimate")]
(sum(abs(perm_stat) >= abs(orig_stat)) + 1)/N
}
res2 <- as.data.frame(unlist(res)) %>% dplyr::mutate(Var1=comp[,1], Var2=comp[,2])
如果我对所有条形orig_stat进行散列处理,它会运行以获得 df 和 df2 中变量之间相关性的系数/估计值。但显然没有进行排列。我应该尝试通过 foreach 使用双循环还是寻找替代方法,例如 Map 的并行版本,例如 mcmapply。
##double loop format
out <- foreach(j=1:ncol(df1), .combine = 'rbind', .packages=c("magrittr", "dplyr")) %:%
foreach(i = 1:ncol(df2), .combine = 'c') %dopar% {
a <- cor.test(df1[,j], df2[,i], method = "spearman")$p.value
}
答:
这里似乎对排列测试的使用存在一些混淆。 已经提供了您需要的信息 - 不需要排列。cor.test
例如,假设返回 p 值 0.05。对于使用 Spearman 的 rho 统计量的双侧检验,解释是 和 之间的 Spearman 秩相关系数比 和 之间的系数在大约 5% 的时间内离 0 更远。cor.test(x, y, method = "spearman")
x
y[sample(length(y))]
x
y
同样,如果我们重复调用 ,我们会看到 p 值小于 0.05,大约有 5% 的时间。展示:cor.test(x, y[sample(length(y))], method = "spearman")
set.seed(293885308L)
x <- runif(20)
y <- runif(20)
correl <- cor(x, y, method = "spearman")
# a single `cor.test`
(p <- cor.test(x, y, method = "spearman")$p.value)
#> [1] 0.04984582
# a permutation test on top of `cor.test`
mean(replicate(1e5, cor.test(x, y[sample(20)], method = "spearman")$p.value) <= p)
#> [1] 0.04982
# a permutation test instead of `cor.test`
mean(abs(replicate(1e6, cor(x, y[sample(20)], method = "spearman"))) >= correl)
#> [1] 0.04973
对于问题中描述的相对较小的数据集,我们可以快速轻松地获得所有成对列组合的 p 值:
df <- as.data.frame(matrix(runif(20*40), 20, 40))
df2 <- as.data.frame(matrix(runif(20*345), 20, 345))
microbenchmark::microbenchmark(
cor.test = mapply(\(y) sapply(df, \(x) cor.test(x, y, method = "spearman")$p.value), df2),
times = 10
)
#> Unit: seconds
#> expr min lq mean median uq max neval
#> cor.test 1.739906 1.753571 1.818344 1.773926 1.841813 1.989383 10
评论
cor.test
cor.test
x
y
x
y
cor.test
df
df2
评论