R语言实现dataframe逻辑规则序列超高速匹配函数需求
R数据框规则序列匹配函数高性能优化需求
原始实现代码
fu <- function(dat , rule , res.only=T){ debug.vec <- rep("no",nrow(dat)) # 规则触发标记 rule.id <- 1 # 规则向量中当前匹配的规则序号 for(i in 1:nrow(dat)){ # 检查第i行是否满足当前待匹配规则rule[rule.id] current_rule <- with(data = dat[i,] , expr = eval(parse(text = rule[rule.id])) ) if(current_rule){ # 规则触发成功 debug.vec[i] <- rule[rule.id] if( rule.id==length(rule) ) break # 所有规则匹配完成则终止循环 rule.id <- rule.id+1 # 匹配下一条规则 }} if(!res.only) return( cbind(dat,debug.vec) ) return( sum(debug.vec!="no")==length(rule) ) }
测试用例
测试数据生成代码
set.seed(123) dat <- as.data.frame(matrix(data = sample(10,30,replace = T),ncol = 3)) colnames(dat) <- paste0("x" ,1:ncol(dat))
生成的数据集内容:
x1 x2 x3 1 3 5 9 2 3 3 3 3 10 9 4 4 2 9 1 5 6 9 7 6 5 3 5 7 4 8 10 8 6 10 7 9 9 7 9 10 10 10 9
规则示例
rule <- c("x1>5 & x2>2" , "x1>x2" , "x3!=4" )
功能说明
该函数按顺序匹配规则向量中的规则:当第k条规则在某行匹配成功后,从下一行开始搜索第k+1条规则,全部规则匹配完成则返回TRUE;若设置res.only = F,会返回新增debug.vec列的原数据集,标记每行匹配到的规则。
调用示例结果:
> fu(dat = dat, rule = rule, res.only = T) [1] TRUE
> fu(dat = dat, rule = rule, res.only = F) x1 x2 x3 debug.vec 1 3 5 9 no 2 3 3 3 no 3 10 9 4 x1>5 & x2>2 4 2 9 1 no 5 6 9 7 no 6 5 3 5 x1>x2 7 4 8 10 x3!=4 8 6 10 7 no 9 9 7 9 no 10 10 10 9 no
匹配逻辑明确
此前其他用户提供的Waldi函数与原函数逻辑不一致,不符合要求,特此明确匹配逻辑:规则[k]触发后,规则[k+1]的搜索必须从dat的下一行开始,以下为逻辑验证示例:
dat <- structure(list(x1 = c(2L, 5L, 1L, 3L, 9L, 2L, 6L, 3L, 3L, 9L), x2 = c(2L, 1L, 6L, 10L, 8L, 10L, 10L, 4L, 6L, 4L), x3 = c(4L, 9L, 8L, 7L, 10L, 1L, 2L, 8L, 3L, 10L)), class = "data.frame", row.names = c(NA, -10L)) rule <- c("x1>5 & x2>2" , "x1>x2" , "x3!=4" ) my_fu(dat = dat, rule = rule, res.only = F)
该场景下仅前两条规则匹配成功,第三条规则无匹配行,函数返回结果如下:
> my_fu(dat = dat, rule = rule, res.only = F) x1 x2 x3 debug.vec 1 2 2 4 no 2 5 1 9 no 3 1 6 8 no 4 3 10 7 no 5 9 8 10 x1>5 & x2>2 6 2 10 1 no 7 6 10 2 no 8 3 4 8 no 9 3 6 3 no 10 9 4 10 x1>x2
> my_fu(dat = dat, rule = rule, res.only = T) [1] FALSE
优化要求
需输出该功能的最高性能实现版本,可使用Rcpp等技术方案优化速度,优化后的函数需完全符合上述匹配逻辑。
内容的提问来源于stack exchange,提问作者mr.T
相关产品推荐
相关产品推荐

