如何在foreach嵌套循环中用cor.test计算数据框相关p值并解决报错?
问题描述
我有两个DataFrame:一个是10行484列,另一个是10行2083列。我想计算第一个DataFrame的484列与第二个DataFrame的2083列之间的Spearman相关系数的p值,输出一个484×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".
我确认两个DataFrame的所有列都是数值型,而且用以下小型测试矩阵时代码能正常运行:
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))
求解决方向。
解决方向
明确并行环境的数据传递:foreach的PSOCK集群不会自动把全局环境的
df1和df2传递给工作节点,即使你加载了相关包,数据对象也需要显式导出。可以在foreach中添加.export参数:out <- foreach(j=1:ncol(df1), .combine = 'rbind', .packages=c("magrittr", "dplyr"), .export = c("df1", "df2")) %:% foreach(i = 1:ncol(df2), .combine = 'c') %dopar% { cor.test(df1[[j]], df2[[i]], method = "spearman")$p.value }或者提前用
clusterExport给集群节点传数据:cl <- makeCluster(10, "PSOCK") clusterExport(cl, c("df1", "df2")) registerDoParallel(cl)修正列提取方式:用
df[,j]提取列时,若DataFrame只有单列或列名特殊,可能返回的是data.frame而非数值向量。改用[[j]]提取纯向量,确保cor.test接收的是数值类型:cor.test(df1[[j]], df2[[i]], method = "spearman")$p.value排查隐藏的非数值/异常列:即使你确认列是数值型,也可能存在
factor误判、NA导致的类型异常,或者全NA列(会触发cor.test报错)。先强制转换所有列为数值型:df1 <- df1 %>% mutate(across(everything(), as.numeric)) df2 <- df2 %>% mutate(across(everything(), as.numeric))再检查并移除全NA列:
df1 <- df1[, colSums(is.na(df1)) != nrow(df1)] df2 <- df2[, colSums(is.na(df2)) != nrow(df2)]优化并行逻辑:嵌套foreach的效率不一定最优,可改用单层循环或向量化函数替代。比如用
outer结合自定义函数(如需并行可搭配parallel包调整):get_spearman_p <- function(j, i) { cor.test(df1[[j]], df2[[i]], method = "spearman")$p.value } out <- outer(1:ncol(df1), 1:ncol(df2), Vectorize(get_spearman_p))
内容的提问来源于stack exchange,提问作者pemb_bex6789
相关产品推荐
相关产品推荐

