R语言使用future包并行模拟时‘row names discarded’警告排查
解决并行模拟合并时的行名警告问题
警告原因
当n_iter>1时,future_lapply返回的每个迭代结果是单个p值,用do.call(rbind, ...)会将这些值拼接成带行名(1到n_iter)的列矩阵;而sim_grid[rowindex,]是单行数据框,行名为原sim_grid的行号。cbind合并两者时,R发现行名长度不匹配,会丢弃行名并抛出警告。n_iter=1时矩阵只有一行,行名和sim_grid的行名一致,所以无警告。
解决方案
直接将future_lapply的结果转为无行名的向量,再作为列合并到参数数据框中,避免行名冲突。以下是两种简洁的实现方式:
方式一:清除中间结果的行名
在合并前手动清除迭代结果矩阵的行名,消除行名冲突:
res_simulation <- do.call("rbind", lapply(seq_len(nrow(sim_grid)), function(rowindex) { print(rowindex) # 执行并行迭代 iter_results <- do.call( "rbind", future_lapply(seq_len(n_iter), function(iter) { one_simulation( n = sim_grid$n[rowindex], mean = sim_grid$mean[rowindex], sd = sim_grid$sd[rowindex] ) }, future.seed = 12457854 + rowindex ) ) rownames(iter_results) <- NULL # 清除行名 cbind(sim_grid[rowindex, ], iter_results) }))
方式二:直接转为向量(更推荐)
利用unlist将future_lapply的列表结果转为向量,再作为新列合并,完全避免行名生成:
res_simulation <- do.call("rbind", lapply(seq_len(nrow(sim_grid)), function(rowindex) { print(rowindex) p_values <- unlist( future_lapply(seq_len(n_iter), function(iter) { one_simulation( n = sim_grid$n[rowindex], mean = sim_grid$mean[rowindex], sd = sim_grid$sd[rowindex] ) }, future.seed = 12457854 + rowindex ) ) # 合并参数和p值向量,命名新列为p_value cbind(sim_grid[rowindex, ], p_value = p_values) }))
修改后的完整代码
# install.packages("future") library(future) # install.packages("future.apply") library(future.apply) options(parallelly.fork.enable = TRUE) # 数据生成函数 data_generating_function <- function(n, mean, sd) { x <- rnorm(n, mean, sd) y <- rnorm(n, mean, sd) + 1 * x return(data.frame(x, y)) } # 单次模拟函数 one_simulation <- function(n, mean, sd) { data <- data_generating_function(n, mean, sd) model <- lm(y ~ x, data = data) p_value <- summary(model)$coefficients[2, 4] return(p_value) } # 模拟参数网格 sim_grid <- expand.grid( n = c(10, 100, 1000), mean = c(0, 1, 2), sd = c(1, 2, 3) ) # 迭代次数 n_iter <- 10 plan(multicore, workers = 3) # 无警告的合并方式 res_simulation <- do.call("rbind", lapply(seq_len(nrow(sim_grid)), function(rowindex) { print(rowindex) p_values <- unlist( future_lapply(seq_len(n_iter), function(iter) { one_simulation( n = sim_grid$n[rowindex], mean = sim_grid$mean[rowindex], sd = sim_grid$sd[rowindex] ) }, future.seed = 12457854 + rowindex ) ) cbind(sim_grid[rowindex, ], p_value = p_values) }))
内容的提问来源于stack exchange,提问作者Linus
相关产品推荐
相关产品推荐

