r - How to calculate "1+1" without using eval(parse(...? -
i have been looking quite while seems answer seems to use eval(parse(text="1+1"))
.
i have column in data frame, has list of strings such "1+1*6", "1*4/3" etc. wish compute these new column without using eval(parse(
functions looking on 8 million rows.
it attempt answer question: given numbers 1:9
find solutions (a_b_c) / (d_e_f) = ghi
, a:i
numbers 1:9
(without repeating) , underscores 1 of 4 operators *, /, +,-
, without repeating.
i created dataframe permutations of 1:9
, each of these calculated permutations of 4 operators.
require(gtools) x <- permutations(n = 9, r = 9, v = 1:9) y <- permutations(n = 4, r = 4, v = c("*", "/", "+", "-")) for(i in 1:nrow(x)){ for(j in 1:nrow(y)){ math <- paste("(", x[i,1], y[j,1], x[i,2],y[j,2], x[i,3],")", "/", "(", x[i,4] ,y[j,3], x[i,5] ,y[j,4], x[i,6],")") equals <- eval(parse(text=math)) sum <- as.numeric(paste0(x[i,7], x[i,8], x[i,9])) if(sum==equals) { print(c(i,j)) } } }
however takes far long, hence trying remove time consuming eval(parse(..
any appreciated. thanks!
freddie
vectorisation key
math <- apply( y, 1, function(j){ paste("(", x[, 1], j[1], x[, 2], j[2], x[, 3],")/(", x[, 4], j[3], x[, 5], j[4], x[, 6], ")") } ) math <- apply(math, 2, paste, collapse = ",") math <- paste("c(", math, ")") equals <- sapply(parse(text = math), eval) sum <-matrix(x[, 7] * 100 + x[, 8] * 10 + x[, 9], nrow = nrow(x), ncol = nrow(y)) abs(sum - equals) < 1e-8
let's see difference in speed is
require(gtools) x <- permutations(n = 9, r = 9, v = 1:9) y <- permutations(n = 4, r = 4, v = c("*", "/", "+", "-"))
x <- x[sample(nrow(x), 40), ] y <- y[sample(nrow(y), 20), ] library(microbenchmark) microbenchmark( loop = for(i in 1:nrow(x)){ for(j in 1:nrow(y)){ math <- paste("(", x[i,1], y[j,1], x[i,2],y[j,2], x[i,3],")", "/", "(", x[i,4] ,y[j,3], x[i,5] ,y[j,4], x[i,6],")") equals <- eval(parse(text=math)) sum <- as.numeric(paste0(x[i,7], x[i,8], x[i,9])) if(sum==equals) { print(c(i,j)) } } }, vectorised = { math <- apply( y, 1, function(j){ paste("(", x[, 1], j[1], x[, 2], j[2], x[, 3],")/(", x[, 4], j[3], x[, 5], j[4], x[, 6], ")") } ) math <- apply(math, 2, paste, collapse = ",") math <- paste("c(", math, ")") equals <- sapply(parse(text = math), eval) sum <-matrix(x[, 7] * 100 + x[, 8] * 10 + x[, 9], nrow = nrow(x), ncol = nrow(y)) abs(sum - equals) < 1e-8 } )
the results:
unit: milliseconds expr min lq mean median uq max neval cld loop 158.666383 162.084918 167.477490 165.880665 170.258076 240.43746 100 b vectorised 8.540623 8.966214 9.613615 9.142515 9.413117 17.88282 100
Comments
Post a Comment