如何在foreach(嵌套循环)中使用cor.test来获取两个数据帧之间的相关性?

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

我有两个数据框。 1 个数据帧是 10 x 484,另一个是 10 x 2083。

我想知道 484 个数据点中的每一个与 2083 个数据点之间的相关性,并以 484 x 2083 矩阵的形式输出。我正在尝试使用 foreach 来加快速度

 registerDoParallel(cl <- makeCluster(10, "PSOCK"))

 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
   }

我得到的错误是

  Error in { : task 1 failed - "'y' must be a numeric vector". 

两个数据帧的所有列值都是数字。当使用下面两个较小的练习矩阵时,上面的代码有效。任何正确方向的指示将不胜感激。

  testmatrix1 <- matrix(rexp(1800, rate=.1), ncol=6)
  colnames(testmatrix1) <- paste0("testmatrix1.Sample", 1:ncol(testmatrix1))
  testmatrix2 <- matrix(rexp(3600, rate=.1), ncol=12)
  colnames(testmatrix2) <- paste0("testmatrix2.Sample", 1:ncol(testmatrix2))
r foreach correlation
1个回答
0
投票

即使在计算超过 1,000,000 个相关性的情况下,基本相关函数也会比双循环快得多,即使它是并行的。并行化并不是没有成本的(就计算开销而言,您仍然在进行超过一百万次计算的双循环。您的代码对我有用:

df1 <- as.data.frame(matrix(runif(10*484, -1, 1), ncol=484))
df2 <- as.data.frame(matrix(runif(10*2083, -1, 1), ncol=2083))

library(doParallel)
registerDoParallel(cl <- makeCluster(10, "PSOCK"))

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
  }

在我的 Apple M2 Max MacBook Pro(96GB RAM)上,这仅花费了 2 分钟多一点的时间。如果你查看

cor.test()
的内部结构,你可以取出你需要的部分并大大加快计算速度。您可以这样做:

pspearman <- function(q, n, lower.tail = TRUE) {
    den <- (n * (n^2 - 1))/6
    r <- 1 - q/den
    pt(r/sqrt((1 - r^2)/(n - 2)), df = n - 2, 
       lower.tail = !lower.tail)
}
R <- cor(df1, df2, method="spearman")
n <- nrow(df1)
q <- (n^3 - n) * (1 - R)/6
p <- 2*apply(q, 1, \(Q)ifelse(Q > (n^3 -n/6), pspearman(Q, n, lower.tail = FALSE), pspearman(Q, n, lower.tail = TRUE)))
if(any(p > 1))p[which(p > 1, arr.ind=TRUE)] <- 1

这样,使用

cor()
并一次性计算整个矩阵上的 p 值大约需要 0.2 秒 - 比双循环快 650 倍(即使是并行化的)。

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