У меня есть датафрейм dat
с данными и вектор rule
с логическими правилами
set.seed(124)
ro <- round(runif (n = 30,1,10),2)
dat <- as.data.frame(matrix(data =ro,ncol = 3)) ; colnames(dat) <- paste0("x" ,1:ncol(dat))
rule <- c("x1 > 5 & x2/2 > 2" , "x1 > x2*2" , "x3!=4")
Мне нужно проверить, верно ли выражение
id <- 2
for(i in 1:nrow(dat)){
cr <- with(data = dat[i,] , expr = eval(parse(text = rule[id])))
print(cr)
}
[1] FALSE
[1] FALSE
[1] FALSE
[1] FALSE
[1] FALSE
[1] TRUE
[1] FALSE
[1] FALSE
[1] FALSE
[1] TRUE
Как это сделать с помощью Rcpp
?
Привет, спасибо за ответ, Смотри внимательно, здесь три правила, а не одно
Будь то одно правило из трех или одно из трех, ваша проблема более глубока, как я пытался объяснить. eval()
очень нужен переводчик. Rcpp не отправляет его, он может вызывать только R или компилировать код, используя непосредственно компилируемые выражения.
Здесь стоит подчеркнуть две вещи:
вам не нужен низкий уровень по всем строкам, так как R векторизован, и это уже быстро
вы можете применить правила к своим данным и вернуть результирующую матрицу
Оба они являются однострочными:
> res <- do.call(cbind, lapply(rule, \(r) with(dat, eval(parse(text=r)))))
> res
[,1] [,2] [,3]
[1,] FALSE FALSE TRUE
[2,] FALSE FALSE TRUE
[3,] TRUE FALSE TRUE
[4,] FALSE FALSE TRUE
[5,] FALSE FALSE TRUE
[6,] FALSE TRUE TRUE
[7,] TRUE FALSE TRUE
[8,] TRUE FALSE TRUE
[9,] TRUE FALSE TRUE
[10,] FALSE TRUE TRUE
>
(Я использовал там анонимную функцию R 4.1.*, вы также можете заменить \(r)
на стандартную function(r)
.)
Поскольку это уже векторизовано, это будет быстрее, чем ваш вызов для каждой строки, и даже если вы сделали это с Rcpp, if не будет (намного) быстрее, чем уже векторизованный код.
Это не очень корректный вопрос. Вы полагаетесь на
eval()
здесь: где / как у Rcpp есть что-то эквивалентное? Это невозможно, поэтому вы в конечном итоге вызоветеeval()
в R из C++. Конечно, существует множество способов построить дерево решений на основе описания. Но они не однострочные. (Кроме того, чего бы это ни стоило, даже с вашим семенем я получаюwith(dat, x1 > 5 & x2/2 > 2 & x1 > x2*2 & x3 != 4)
возврат всехFALSE
.