R语言带概率迁移的向量采样:要求新向量与原向量无同位置重复元素
带位置冲突约束的加权无放回采样实现方案
你需要的两种可落地实现思路如下,均天然支持V1元素非连续的场景:
前置说明
原始向量定义:
V1 <- seq(1:21) # 输出 [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
原有加权采样规则:元素<=10对应采样权重0.97,元素>10对应采样权重0.03,无放回采样。
新增约束:对任意位置i,满足v2[i] != V1[i]
实现思路
- 思路1:拒绝采样法(适合长度小于100的短向量,实现成本极低)
逻辑简单直接,冲突概率低的场景下效率极高:- 按照原有加权规则生成无放回采样的候选v2
- 全局校验所有位置是否满足
v2[i] != V1[i] - 符合约束就输出,不符合就重新采样,直到得到合格结果
示例代码:
# 支持任意非连续自定义V1 V1 <- c(1,3,5,7,9,11,13,15,17,19,21,2,4,6,8,10,12,14,16,18,20) # 可自定义每个元素的权重,不需要和元素值强绑定 prob_vec <- ifelse(V1 <= 10, 0.97, 0.03) # 循环采样直到符合约束 repeat{ v2 <- sample(V1, prob = prob_vec, replace = FALSE) if(all(v2 != V1)) break } - 思路2:逐位构造法(适合长向量,无重复采样开销)
从根源上避免位置冲突,不需要重复试错:- 初始化可用元素池为全部V1元素,对应权重为预设的概率值
- 从第1位到最后一位逐位生成v2的元素:
- 从当前可用元素池中排除和V1第i位相同的元素
- 按照剩余元素的权重概率采样得到v2[i]
- 将采样到的元素从可用元素池和权重向量中移除
- 全部位置生成完成后直接输出v2
示例代码:
V1 <- c(1,3,5,7,9,11,13,15,17,19,21,2,4,6,8,10,12,14,16,18,20) prob_vec <- ifelse(V1 <= 10, 0.97, 0.03) n <- length(V1) v2 <- numeric(n) available <- V1 available_prob <- prob_vec for(i in 1:n){ # 排除当前位置和原向量相同的元素 idx <- available != V1[i] candidate <- available[idx] candidate_prob <- available_prob[idx] # 加权采样当前位元素 selected <- sample(candidate, size = 1, prob = candidate_prob) v2[i] <- selected # 移除已选元素避免重复 remove_idx <- which(available == selected)[1] available <- available[-remove_idx] available_prob <- available_prob[-remove_idx] }
内容的提问来源于stack exchange,提问作者sean stankowski
相关产品推荐
相关产品推荐

