机器学习中按Treatment与Bio分组拆分训练/测试/验证集的方法
问题描述
需要将包含Control和TP两个Treatment组的数据集拆分为训练集、测试集和验证集,每组下有Bio 1-4的子分组。拆分规则为:若Control 1被分到训练集,则所有Control 1和TP 1样本都需归入训练集(实际数据中各Bio分组样本量不均)。
示例数据集:
Sample Treatment Bio 285.945846 286.9638976 288.1004758 288.8109355 Control1_A13 Control 1 0.003535191 0.001777255 0.004729780 0.002364995 Control1_A14 Control 1 0.005063256 0.000110063 0.006249624 0.001041584 Control1_A15 Control 1 0.004262099 0.000836256 0.004277461 0.002699177 Control2_B13 Control 2 0.002411720 0.000466887 0.001129674 0.001109870 Control2_B14 Control 2 0.003085647 0.001831629 0.002482230 0.000000000 Control2_B15 Control 2 0.001996473 0.001060616 0.003995243 0.001369387 Control3_C13 Control 3 0.000299744 0.000851944 0.002808119 0.004065315 Control3_C14 Control 3 0.003187073 0.000591202 0.006833653 0.001713096 Control3_C15 Control 3 0.003692511 0.000262144 0.004673039 0.000126174 Control4_D13 Control 4 0.003369294 0.001087459 0.005171894 0.000675702 Control4_D14 Control 4 0.003818057 0.000838719 0.005513885 0.000458708 Control4_D15 Control 4 0.002572840 0.000257058 0.003537029 0.000009040 LX2+TP1_E1 TP 1 0.003347067 0.001231945 0.008181087 0.004436654 LX2+TP1_E2 TP 1 0.001552547 0.001463769 0.008864838 0.002728083 LX2+TP1_E3 TP 1 0.003224648 0.000812735 0.008518836 0.004303950 LX2+TP2_F1 TP 2 0.001705551 0.000182659 0.000911028 0.000240785 LX2+TP2_F2 TP 2 0.000760944 0.000759464 0.002486596 0.002377735 LX2+TP2_F3 TP 2 0.001034440 0.000647382 0.008146538 0.001028800 LX2+TP3_G1 TP 3 0.003660741 0.001260433 0.008046637 0.003182006 LX2+TP3_G2 TP 3 0.001802459 0.000547580 0.004882082 0.004121552 LX2+TP3_G3 TP 3 0.003590003 0.000089100 0.002801237 0.000403527 LX2+TP4_H1 TP 4 0.002831592 0.001534135 0.009151124 0.003021942 LX2+TP4_H2 TP 4 0.001863099 0.000959953 0.008284829 0.005169246 LX2+TP4_H3 TP 4 0.005649448 0.001959382 0.011814467 0.004110110
尝试过两种方法,但都存在问题:
- 方法1:仅按Treatment分组拆分,未考虑Bio分组的关联规则
set.seed(1234) inTraining <- createDataPartition(vis_data2$Treatment, p=0.6, list=FALSE) training.set <- vis_data2[inTraining,] Totalvalidation.set <- vis_data2[-inTraining,] # 拆分剩余40%为测试集和验证集各20% inValidation <- createDataPartition(Totalvalidation.set$Treatment, p=0.5, list=FALSE) testing.set <- Totalvalidation.set[inValidation,] validation.set <- Totalvalidation.set[-inValidation,]
- 方法2:尝试按Bio分组拆分,但运行时常出现NA值,且分组不符合要求
set.seed(1) # 拆分训练集和验证集 Y1 = vis_data2[,1] # 定义处理组列 g1 = vis_data2[,3] # 定义分组列 final_vis_data <- sample.split(Y1,SplitRatio = 0.5,group = g1) table(Y1,final_vis_data) # 查看拆分比例 split(final_vis_data,g1) # 尝试保持同组样本在一起 full_train_set <- vis_data2[ final_vis_data,] test.set <- vis_data2[!final_vis_data,] # 拆分训练集为训练集和测试集 Y2 = full_train_set[,1] # 定义处理组列 g2 = full_train_set[,3] # 定义分组列 final_vis_data2 <- sample.split(Y2,SplitRatio = 0.5,group = g2) table(Y2,final_vis_data2) # 查看拆分比例 split(final_vis_data2,g2) # 尝试保持同组样本在一起 test.set <- full_train_set[final_vis_data2,1:3] validation.set <- full_train_set[!final_vis_data2,1:3]
解决方案
核心思路是:以Bio编号为基本拆分单元(保证Control N和TP N绑定),先对Bio单元进行比例拆分,再批量分配对应单元的所有样本到训练/测试/验证集。
完整代码
set.seed(1234) # 设置随机种子保证结果可重复 # 替换为你的数据读取方式,比如read.csv或read.table vis_data2 <- read.table("your_data_file.txt", header = TRUE) # 提取所有唯一的Bio分组编号 bio_groups <- unique(vis_data2$Bio) # 第一步:拆分训练集的Bio单元(示例为60%比例) train_bio <- sample(bio_groups, size = round(length(bio_groups)*0.6)) remaining_bio <- setdiff(bio_groups, train_bio) # 第二步:从剩余单元拆分测试集和验证集(各占剩余的50%) test_bio <- sample(remaining_bio, size = round(length(remaining_bio)*0.5)) val_bio <- setdiff(remaining_bio, test_bio) # 第三步:根据Bio单元分配对应所有样本 training.set <- vis_data2[vis_data2$Bio %in% train_bio, ] testing.set <- vis_data2[vis_data2$Bio %in% test_bio, ] validation.set <- vis_data2[vis_data2$Bio %in% val_bio, ] # 验证拆分结果 cat("训练集包含的Bio分组:", paste(train_bio, collapse = ","), "\n") cat("测试集包含的Bio分组:", paste(test_bio, collapse = ","), "\n") cat("验证集包含的Bio分组:", paste(val_bio, collapse = ","), "\n") # 查看各数据集的Treatment和Bio分布 table(training.set$Treatment, training.set$Bio) table(testing.set$Treatment, testing.set$Bio) table(validation.set$Treatment, validation.set$Bio)
代码说明
bio_groups提取所有唯一Bio编号,确保拆分时以整个Bio组为单位,保证Control和TP的同编号样本绑定sample()对Bio单元随机抽样,完全符合需求中"同Bio编号样本同属一个数据集"的规则- 可根据实际需求调整拆分比例,比如修改
round(length(bio_groups)*0.6)中的数值 - 最后通过
%in%筛选样本,批量分配效率高且不会出现分组错误
内容的提问来源于stack exchange,提问作者Ruth Walker
相关产品推荐
相关产品推荐

