R语言蒙特卡洛模拟函数中采样点距离约束模块的实现方法
实现思路
要满足最小距离采样约束,我们可以封装专用的约束采样函数,替换原有代码里的无约束随机采样逻辑即可:
- 单次采样时先随机选取第一个样本点加入结果集
- 后续每抽取一个候选点,就和结果集内所有已选点计算距离,只有所有距离都≥m时才将该点加入结果集
- 重复步骤2直到结果集的样本量达到要求
完整可运行代码
# --------------- 原有基础代码 --------------- ## 创建示例数据集 # x、y为坐标 x <- c(1:100) y <- rev(c(1:100)) ## z、w为土壤检测值 set.seed(2345) z <- rnorm(100,mean=50, sd=10) set.seed(2345) w <- rnorm(100, mean=75, sd=5) data <- data.frame(x, y, z, w) # 距离计算函数 calc.dist <- function(x1, y1, x2, y2) { d <- sqrt(((x2 - x1)^2) + ((y2 - y1)^2)) return(d) } # --------------- 新增约束采样函数 --------------- # 参数说明: # dat: 完整样本数据集 # n_sample: 需要抽取的样本量 # min_dist: 两点之间最小距离阈值(即你说的m) constrained_sample <- function(dat, n_sample, min_dist) { # 初始化结果索引向量 selected_idx <- c() # 所有可选样本的索引 available_idx <- seq_len(nrow(dat)) # 第一个点随机选 first_idx <- sample(available_idx, 1) selected_idx <- c(selected_idx, first_idx) available_idx <- setdiff(available_idx, first_idx) # 循环选剩下的点 while(length(selected_idx) < n_sample) { # 随机选一个候选点 cand_idx <- sample(available_idx, 1) # 计算候选点和所有已选点的距离 dists <- mapply(calc.dist, dat$x[cand_idx], dat$y[cand_idx], dat$x[selected_idx], dat$y[selected_idx]) # 所有距离都≥最小阈值则入选 if(all(dists >= min_dist)) { selected_idx <- c(selected_idx, cand_idx) available_idx <- setdiff(available_idx, cand_idx) } } # 返回采样后的数据集 return(dat[selected_idx, ]) } # --------------- 修改后的采样循环 --------------- # 自定义最小距离m,这里示例设为20,可根据你的需求修改 m <- 20 # 初始化结果列表 data.step.sim.list <- list() # 样本量逐步递增采样 for(i in seq_len(nrow(data))) { # 每个样本量重复100次,替换原sample为constrained_sample thisdat <- replicate(100, constrained_sample(data, n_sample = i, min_dist = m), simplify = FALSE) data.step.sim.list[[i]] <- thisdat }
注意事项
- 提前确认设置的最小距离
m不要过大,如果当前数据集里最多只能选出k个两两距离≥m的点,当采样量i>k时会陷入死循环。可以先提前测试给定m下数据集的最大可采样量,或者在constrained_sample函数里加最大迭代次数判断避免卡死。 - 如果你的数据集坐标本身带单位,直接按单位设置
m的值即可,不需要额外转换距离计算逻辑。
内容的提问来源于stack exchange,提问作者Vaughn Reed
相关产品推荐
相关产品推荐

