在R语言中按约束将含重复值的向量随机分组
带重复值向量的约束随机分组解决方案
需求说明
需要将包含重复值的数值向量随机分配到数量更少的分组中,满足以下约束:
- 每组元素数量在2-4之间
- 同一分组内无重复的原始数值
- 所有元素必须分配到分组中
问题分析
原代码split(values, sample(groups, length(values), repl = TRUE))的问题在于:
- 随机分配时未限制每组元素数量,会出现1个或超过4个元素的分组
- 未规避同一原始数值的多个实例被分到同一组的情况
解决方案代码
我们可以通过给重复值添加唯一标识、迭代构建符合约束的分组来解决问题:
# 示例数据 values <- c(2499,2499,2522,2522,2522,2522,2648,2648,2652,2652,2670,2670,2689,2689,2690,2690,2693,2693,2700,2700,2706,2706,2714,2714,2730,2730,2738,2738,2740,2740,2765,2765,2768,2768,2773,2773,2783,2783,2794,2794,2798,2798,2807,2807,2812,2812,2831,2831,2831,2835,2835,2836,2836,2836,2844,2844,2844,2846,2846,2846,2883,2883,2964,2964) # 1. 给每个重复值添加唯一后缀,区分同一数值的不同实例 values_with_id <- paste0(values, "_", ave(values, values, FUN = seq_along)) # 2. 定义生成符合约束分组的函数 create_valid_groups <- function(items, min_size = 2, max_size = 4) { remaining <- items groups <- list() while (length(remaining) > 0) { # 确定当前组的可选大小范围 current_max <- min(max_size, length(remaining)) current_size <- sample(min_size:current_max, 1) # 随机选取元素,确保组内无重复原始值 valid_group <- NULL while (is.null(valid_group)) { candidate <- sample(remaining, current_size) original_vals <- sub("_\\d+$", "", candidate) if (length(unique(original_vals)) == current_size) { valid_group <- candidate } } # 将符合条件的组加入结果,并移除已分配元素 groups[[length(groups) + 1]] <- valid_group remaining <- setdiff(remaining, valid_group) } # 还原原始数值并给分组命名 groups <- lapply(groups, function(x) as.numeric(sub("_\\d+$", "", x))) names(groups) <- paste0("Group", seq_along(groups)) return(groups) } # 3. 生成符合要求的分组 result_groups <- create_valid_groups(values_with_id)
验证约束
可以通过以下代码验证分组是否符合要求:
# 检查每组元素数量(应全部在2-4之间) sapply(result_groups, length) # 检查每组是否存在重复值(应全部返回TRUE) sapply(result_groups, function(x) length(unique(x)) == length(x))
注意事项
- 确保总元素数满足分组可行性:总元素数
n需满足ceil(n/4) ≤ 目标组数 ≤ floor(n/2),示例数据共64个元素,目标组数26在16-32之间,完全可行。 - 若剩余元素不足
min_size(如最后剩余1个),需提前调整分组逻辑,但示例数据的元素数量不会出现这种情况。
内容的提问来源于stack exchange,提问作者James Daniel Johnston
相关产品推荐
相关产品推荐

