You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

正确理解R语言replicate()函数用法及批量运行函数报错修复

问题描述

我编写了如下自定义R函数:

library(dplyr)

var_1 <- rnorm(100, 10, 10)
var_2 <- rnorm(100, 1, 10)
var_3 <- rnorm(100, 5, 10)
response <- rnorm(100, 1, 1)
my_data <- data.frame(var_1, var_2, var_3, response)
my_data$id <- 1:100

simulate <- function() {
  results <- list()
  results2 <- list()
  for (i in 1:100) {
    iteration_i <- i
    sample_i <- my_data[sample(nrow(my_data), 10), ]
    results_tmp <- data.frame(iteration_i, sample_i)
    results[[i]] <- results_tmp
  }
  results_df <- do.call(rbind.data.frame, results)
  test_1 <- data.frame(results_df %>% 
                         group_by(id) %>% 
                         filter(iteration_i == min(iteration_i)) %>% 
                         distinct)
  summary_file <- data.frame(test_1 %>% 
                               group_by(iteration_i) %>% 
                               summarise(Count=n()))
  cumulative <- cumsum(summary_file$Count)
  summary_file$Cumulative <- cumulative
  summary_file$unobserved <- 100 - cumulative
  return(summary_file)
}

单独调用该函数可得到正常输出:

> head(simulate())
  iteration_i Count Cumulative unobserved
1           1    10         10         90
2           2     7         17         83
3           3    10         27         73
4           4     5         32         68
5           5     7         39         61
6           6     8         47         53

我的需求是将该函数重复运行10次,把所有运行结果合并为单个数据文件。尝试用4种批量运行写法均失败,失败代码如下:

# Method 1 : Did not work
n_replicates = 10
iterations_required <- replicate(n_replicates, {
  simulate() 
})

# Method 2: Did not work
lapply(seq_len(10), simulate(1))

# Method 3: Did Not Work
library(purrr)
rerun(10, simulate(1))

# Method 4: Did Not Work
lapply(seq_len(10), simulate)

目前仅手动编写for循环可以正常得到目标结果,可运行代码如下:

# works fine!
results <- list()
for (i in 1:10) { 
  game_i <- i
  s_i <- simulate()
  results_tmp <- data.frame(game_i, s_i)
  results[[i]] <- results_tmp
}

final_file <- do.call(rbind.data.frame, results)

我的问题:上述4种批量运行方法无法正常工作的原因是什么?如何修正这些写法实现需求?

失败原因
  • 方法1(replicate写法):replicate()默认参数simplify=TRUE,会自动把每次运行返回的数据框按列拆解,拼接成二维矩阵/数组,不会保留列表结构,最终得到的是宽格式的拼接结果,完全不符合按行合并、带批次号的需求。
  • 方法2(lapply写simulate(1)):存在两个错误:一是lapply的第二个参数需要接收函数对象,直接写simulate(1)会在调用lapply的瞬间就执行1次simulate,把执行结果而非函数传给lapply,无法实现迭代运行;二是定义的simulate()是无参数函数,传入参数1会直接触发unused argument (1)的报错。
  • 方法3(purrr::rerun写simulate(1)):错误和方法2完全一致:直接写simulate(1)会当场执行一次函数,且多余的参数1会触发报错,无法完成10次重复运行。
  • 方法4(lapply传simulate):这个写法本身可以正常完成10次simulate运行,返回包含10个数据框的列表,但缺少两个关键步骤:没有给每次运行结果添加game_i批次标识,也没有最后调用行合并函数把列表拼成单个数据框,拿到的是列表而非预期的最终数据框,因此误以为运行失败。
修正方案

以下所有修正写法的输出,和手写for循环得到的final_file结构完全一致。

方法1修正:replicate版本

replicate必须设置simplify = FALSE禁止自动简化结果,保留数据框列表结构,再添加批次号合并即可:

n_replicates = 10
# 得到10次运行结果的列表
iterations_list <- replicate(n_replicates, simulate(), simplify = FALSE)
# 加批次号+合并为单个数据框
final_file <- do.call(
  rbind.data.frame,
  lapply(seq_along(iterations_list), function(i) {
    data.frame(game_i = i, iterations_list[[i]])
  })
)

如果已经加载dplyr,合并步骤可以简化:

final_file <- bind_rows(iterations_list, .id = "game_i") %>%
  mutate(game_i = as.integer(game_i))

方法2修正:lapply版本

lapply第二个参数必须传入函数对象,不能直接传入函数执行结果,无参数函数可以用匿名函数包裹调用逻辑:

iterations_list <- lapply(seq_len(10), function(x) simulate())
# 后续合并逻辑和方法1一致
final_file <- do.call(
  rbind.data.frame,
  lapply(seq_along(iterations_list), function(i) {
    data.frame(game_i = i, iterations_list[[i]])
  })
)

方法3修正:purrr::rerun版本

rerun内直接传入无参数的函数调用表达式(不要传多余参数),配合purrr的行绑定函数可以快速得到结果:

library(purrr)
iterations_list <- rerun(10, simulate())
# 直接合并并自动生成批次号
final_file <- list_rbind(iterations_list, names_to = "game_i") %>%
  mutate(game_i = as.integer(game_i))

方法4修正:原lapply传simulate版本

原写法已经可以得到10次运行的结果列表,只需要补充加批次号、合并的步骤即可:

iterations_list <- lapply(seq_len(10), simulate)
# 后续合并逻辑和方法1一致
final_file <- do.call(
  rbind.data.frame,
  lapply(seq_along(iterations_list), function(i) {
    data.frame(game_i = i, iterations_list[[i]])
  })
)

内容的提问来源于stack exchange,提问作者stats_noob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 11:06:20