如何在R语言中实现近似筛选最大方差基因型子集的迭代算法?
用R实现近似寻找最大方差子集的方案
没问题,我帮你搞定这个需求——因为穷举所有子集完全不现实,咱们就用你提出的贪心迭代近似方法,从20个基因型里选出10个方差最大的子集,下面是具体实现:
第一步:准备示例数据
首先先把你给的示例数据定义好:
# 示例基因型数据 Genotype <-c("BK001","BK002","BK003","BK004","BK005","BK006","BK007","BK008","BK009","BK010", "BK011","BK012","BK013","BK014","BK015","BK016","BK017","BK018","BK019","BK020") Protein <- c(13.25287,14.34778,13.87116,14.00869,14.77897,14.43378,15.89361,15.96695,13.78778, 12.84457,12.99955,14.28378,14.15799,12.42578,14.80507,13.56095,15.26557,14.45378,13.06739, 14.34230) my_df <- data.frame(Genotype, Protein)
第二步:实现核心逻辑
咱们按照你提出的流程来,不过我优化了初始步骤——直接从所有3元素组合里找方差最大的,比“min+max+随机”的初始候选更接近最优,当然如果你坚持原初始方式,后面我会给出修改方案。
2.1 定义辅助函数
先写个小函数用来计算子集的方差:
# 计算给定索引对应的Protein子集的方差 get_subset_var <- function(subset_indices, df) { var(df$Protein[subset_indices]) }
2.2 找到最优初始3元素子集
遍历所有可能的3元素组合,选出方差最大的那个作为迭代起点:
# 生成所有3元素的索引组合 all_3comb <- combn(nrow(my_df), 3) # 计算每个组合的方差 var_3comb <- apply(all_3comb, 2, get_subset_var, df = my_df) # 找到方差最大的3元素组合 max_var_3_idx <- all_3comb[, which.max(var_3comb)] current_subset <- my_df[max_var_3_idx, ] remaining_df <- my_df[-max_var_3_idx, ]
2.3 迭代扩展子集到目标大小
每次从剩余元素里选一个加入当前子集,让新子集的方差最大,直到子集大小达到10:
# 目标子集大小 target_size <- 10 # 开始迭代 while(nrow(current_subset) < target_size) { candidate_vars <- c() # 逐个测试剩余元素加入后的方差 for(i in 1:nrow(remaining_df)) { temp_subset <- rbind(current_subset, remaining_df[i, ]) candidate_vars <- c(candidate_vars, var(temp_subset$Protein)) } # 选出让方差最大的元素 best_idx <- which.max(candidate_vars) # 更新当前子集和剩余数据 current_subset <- rbind(current_subset, remaining_df[best_idx, ]) remaining_df <- remaining_df[-best_idx, ] # 可选:打印进度,方便追踪 cat(sprintf("当前子集大小:%d,当前方差:%.4f\n", nrow(current_subset), var(current_subset$Protein))) }
第三步:查看结果
运行完循环后,直接输出最终的子集和它的方差:
cat("方差最大的10个基因型子集:\n") print(current_subset) cat(sprintf("\n该子集的Protein方差为:%.4f", var(current_subset$Protein)))
可选:使用你原描述的初始子集
如果你想严格按照“min+max+任意剩余元素”作为初始,替换掉2.2的代码即可:
# 找到Protein最小和最大的基因型索引 min_idx <- which.min(my_df$Protein) max_idx <- which.max(my_df$Protein) # 从剩余元素里随机选一个 remaining_idx <- setdiff(1:nrow(my_df), c(min_idx, max_idx)) random_idx <- sample(remaining_idx, 1) # 初始化子集 current_subset <- my_df[c(min_idx, max_idx, random_idx), ] remaining_df <- my_df[-c(min_idx, max_idx, random_idx), ]
注意事项
- 这个方法是贪心近似算法:它每一步都选当前最优的选项,不能保证找到全局绝对最优的子集,但在计算效率和结果质量之间做了很好的平衡,非常适合你提到的150选75这种大规模场景。
- 如果你需要多次运行取更稳定的结果,可以把初始随机选择(如果用原初始方式)或者整个流程重复几次,取方差最大的那个最终子集。
内容的提问来源于stack exchange,提问作者IvanaOs
相关产品推荐
相关产品推荐

