编写支持group_by的友好型R函数:自定义验证列生成求助
优化分组数据的训练/验证集拆分函数
核心优化思路
放弃使用已逐步弃用的do(),转而利用dplyr的分组上下文自动特性,结合mutate或group_modify()实现兼容分组/非分组数据的流畅管道函数。
方案1:极简通用版(兼容分组与非分组)
dplyr在分组数据中调用n()时,会自动识别为组内行数;非分组时则返回总行数,因此无需额外判断即可实现通用拆分:
split_train_val <- function(data, train_prop = 0.75) { data %>% dplyr::mutate( # 按比例随机分配训练集标记 training = sample(c(TRUE, FALSE), size = dplyr::n(), replace = TRUE, prob = c(train_prop, 1 - train_prop)), # 验证集与训练集互斥 validation = !training ) }
使用示例:
- 非分组数据:
mtcars %>% split_train_val() - 分组数据:
mtcars %>% dplyr::group_by(cyl) %>% split_train_val()
方案2:带精细控制的进阶版
如果需要限制每组训练集的最小样本量(避免小分组拆分后样本不足),可以用group_modify()实现:
split_train_val <- function(data, train_prop = 0.75, min_train = 2) { data %>% dplyr::group_modify(function(group, ...) { n_group <- nrow(group) # 确保训练集样本数不低于设定最小值 train_n <- max(floor(train_prop * n_group), min_train) train_idx <- sample(n_group, train_n) group %>% dplyr::mutate( training = dplyr::row_number() %in% train_idx, validation = !training ) }) %>% dplyr::ungroup() # 可选:根据需求保留/取消分组状态 }
为什么if()+do()会失败?
do()的语法逻辑与现代dplyr管道风格不兼容,容易出现上下文环境混淆(比如变量引用、分组识别出错)。而mutate/group_modify()是为分组数据操作设计的原生函数,能自动适配分组上下文,代码更简洁可靠。
内容的提问来源于stack exchange,提问作者Niall Marsay
相关产品推荐
相关产品推荐

