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

如何用apply、lapply替代R语言中的for循环?

用apply/lapply替代Box-Muller方法的for循环

首先你的原函数存在两个问题:一是未初始化samp1和samp2向量,运行时会报错;二是函数没有返回生成的样本结果。下面给出几种用apply系列函数替代的写法,同时修正这些问题:

方法1:用lapply生成样本列表再整理

lapply会遍历每个索引执行样本生成逻辑,返回包含每组(X1,X2)的列表,最后将列表转成矩阵拆分出两个样本向量:

f_lapply <- function(n) {
  samples_list <- lapply(1:n, function(i) {
    U1 <- runif(1)
    U2 <- runif(1)
    X1 <- sqrt(-2*log(U1))*cos(2*pi*U2)
    X2 <- sqrt(-2*log(U1))*sin(2*pi*U2)
    c(X1, X2)
  })
  samples_mat <- do.call(rbind, samples_list)
  list(samp1 = samples_mat[,1], samp2 = samples_mat[,2])
}

方法2:用apply基于矩阵处理

先一次性生成所有需要的均匀分布随机数,再用apply逐行计算对应的正态样本:

f_apply <- function(n) {
  # 一次性生成n组U1和U2,比循环里每次调用runif更高效
  U_mat <- matrix(runif(2*n), ncol = 2)
  samples_mat <- apply(U_mat, 1, function(u) {
    U1 <- u[1]
    U2 <- u[2]
    X1 <- sqrt(-2*log(U1))*cos(2*pi*U2)
    X2 <- sqrt(-2*log(U1))*sin(2*pi*U2)
    c(X1, X2)
  })
  # 转置矩阵让每行对应一组样本
  samples_mat <- t(samples_mat)
  list(samp1 = samples_mat[,1], samp2 = samples_mat[,2])
}

额外建议:优先用向量化操作

其实在R里,最高效的写法是直接用向量运算,完全不需要循环或apply系列——因为R的向量运算底层由C实现,速度远快于循环类操作:

f_vectorized <- function(n) {
  U1 <- runif(n)
  U2 <- runif(n)
  sqrt_term <- sqrt(-2*log(U1))
  samp1 <- sqrt_term * cos(2*pi*U2)
  samp2 <- sqrt_term * sin(2*pi*U2)
  list(samp1 = samp1, samp2 = samp2)
}

以上三种写法都能生成符合要求的标准正态分布样本,其中向量化版本的性能最优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 09:25:41