R语言数据集添加分组变量的更优实现方法咨询
R语言数据集分类的优化实现方案
你当前的实现采用eval(parse())配合循环的方式存在调试难度高、运行效率低、易触发语法错误的问题,以下是几种可实现完全相同效果的更优方案:
方案1:使用dplyr的case_when()(最推荐,简洁易读)
这是目前同类需求下最常用的实现方式,代码逻辑清晰,无需手动处理判断优先级:
library(dplyr) Items <- rep(c("cleats","whistle","VAR","Penalty","Bat","Pink Ball","White Ball","Super-Over","Hoops","Men's Rugby","Women's rugby"),5) dt <- data.frame(Items) dt <- dt %>% mutate(Classification = case_when( Items %in% c('cleats','whistle','VAR','Penalty') ~ 'Football', Items %in% c('Bat','Pink Ball','White Ball','Super-Over') ~ 'Cricket', grepl('Rugby|rugby', Items) ~ 'Rugby', TRUE ~ 'Other Sports' ))
方案2:Base R 原生实现(无需加载第三方包)
如果你不想引入依赖包,可以用嵌套ifelse实现,完全不用循环和表达式解析:
Items <- rep(c("cleats","whistle","VAR","Penalty","Bat","Pink Ball","White Ball","Super-Over","Hoops","Men's Rugby","Women's rugby"),5) dt <- data.frame(Items) dt$Classification <- ifelse( dt$Items %in% c('cleats','whistle','VAR','Penalty'), 'Football', ifelse( dt$Items %in% c('Bat','Pink Ball','White Ball','Super-Over'), 'Cricket', ifelse( grepl('Rugby|rugby', dt$Items), 'Rugby', 'Other Sports' ) ) )
方案3:高可维护性规则迭代实现(适合分类规则频繁调整的场景)
如果你的分类规则经常需要增减,可以把规则单独抽离成配置,用purrr的迭代功能实现,修改规则不需要调整核心逻辑:
library(purrr) Items <- rep(c("cleats","whistle","VAR","Penalty","Bat","Pink Ball","White Ball","Super-Over","Hoops","Men's Rugby","Women's rugby"),5) dt <- data.frame(Items) # 单独定义分类规则,新增规则仅需在此列表添加即可 rules <- list( list(pred = function(x) x %in% c('cleats','whistle','VAR','Penalty'), val = 'Football'), list(pred = function(x) x %in% c('Bat','Pink Ball','White Ball','Super-Over'), val = 'Cricket'), list(pred = function(x) grepl('Rugby|rugby', x), val = 'Rugby'), list(pred = function(x) rep(TRUE, length(x)), val = 'Other Sports') ) # 迭代应用规则生成分类列 dt$Classification <- reduce(rules, function(res, rule) { ifelse(is.na(res) & rule$pred(dt$Items), rule$val, res) }, .init = rep(NA_character_, nrow(dt)))
以上三种方案均规避了原实现中eval(parse())的安全风险和调试难题,运行效率和可维护性均优于原有循环实现。
内容的提问来源于stack exchange,提问作者Din
相关产品推荐
相关产品推荐

