# Evaluate different logical conditions from string for each row

I have a `data.frame` like this:

``````  value     condition
1  0.46   value > 0.5
2  0.96 value == 0.79
3  0.45 value <= 0.65
4  0.68 value == 0.88
5  0.57   value < 0.9
6  0.10  value > 0.01
7  0.90  value >= 0.6
8  0.25  value < 0.91
9  0.04   value > 0.2

structure(list(value = c(0.46, 0.96, 0.45, 0.68, 0.57, 0.1, 0.9,
0.25, 0.04), condition = c("value > 0.5", "value == 0.79", "value <= 0.65",
"value == 0.88", "value < 0.9", "value > 0.01", "value >= 0.6",
"value < 0.91", "value > 0.2")), class = "data.frame", row.names = c(NA,
-9L))

``````

I would like to evaluate the strings in the `condition` column for every row.

So the result would look like this.

``````  value     condition  goal
1  0.46   value > 0.5 FALSE
2  0.96 value == 0.79 FALSE
3  0.45 value <= 0.65  TRUE
4  0.68 value == 0.88 FALSE
5  0.57   value < 0.9  TRUE
6  0.10  value > 0.01  TRUE
7  0.90  value >= 0.6  TRUE
8  0.25  value < 0.91  TRUE
9  0.04   value > 0.2 FALSE
``````

I suppose there is a handy NSE solution within the `dplyr` framework. I have experimented with `!!` and `expr()` and others. I got some promising results when trying to subset by `condition` using

``````result <- df[0,]
for(i in 1:nrow(df)) {
result <- rbind(result, filter_(df[i,], bquote(.(df\$condition[i]))))
}

``````

But I don't like the solution and it's not exactly what I'm after.

I hope someone can help.

UPDATE: I'm trying to avoid `eval(parse(..))`.

Not entirely sure whether you are looking for something like this, however, you can also use `lazy_eval()` from `lazyeval`:

``````df %>%
rowwise() %>%
mutate(res = lazy_eval(sub("value", value, condition)))

value condition     res
<dbl> <chr>         <lgl>
1 0.46  value > 0.5   FALSE
2 0.96  value == 0.79 FALSE
3 0.45  value <= 0.65 TRUE
4 0.68  value == 0.88 FALSE
5 0.570 value < 0.9   TRUE
6 0.1   value > 0.01  TRUE
7 0.9   value >= 0.6  TRUE
8 0.25  value < 0.91  TRUE
9 0.04  value > 0.2   FALSE
``````

And even though it is very close to `eval(parse(...))`, a possibility is also using `parse_expr()` from `rlang`:

``````df %>%
rowwise() %>%
mutate(res = eval(rlang::parse_expr(condition)))
``````

One straightforward and easy solution would be using `eval(parse...`

``````library(dplyr)

df %>%
rowwise() %>%
mutate(goal = eval(parse(text = condition)))

# A tibble: 9 x 3
#  value condition     goal
#  <dbl> <chr>         <lgl>
#1 0.46  value > 0.5   FALSE
#2 0.96  value == 0.79 FALSE
#3 0.45  value <= 0.65 TRUE
#4 0.68  value == 0.88 FALSE
#5 0.570 value < 0.9   TRUE
#6 0.1   value > 0.01  TRUE
#7 0.9   value >= 0.6  TRUE
#8 0.25  value < 0.91  TRUE
#9 0.04  value > 0.2   FALSE
``````

However, I would recommend reading some posts before using it.

• That's true of course, I know `eval(parse(..))` but I try to find a solution without it using NSE in `dplyr`. I should have been more specific about it. – Humpelstielzchen Apr 23 at 8:56

Using match.fun:

``````# get function, and the value
myFun <- lapply(strsplit(df1\$condition, " "), function(i){
list(f = match.fun(i[ 2 ]),
v = as.numeric(i[ 3 ]))
})

df1\$goal <- mapply(function(x, y){
x[[ "f" ]](y, x[ "v" ])
}, x = myFun, y = df1\$value)

#   value     condition  goal
# 1  0.46   value > 0.5 FALSE
# 2  0.96 value == 0.79 FALSE
# 3  0.45 value <= 0.65  TRUE
# 4  0.68 value == 0.88 FALSE
# 5  0.57   value < 0.9  TRUE
# 6  0.10  value > 0.01  TRUE
# 7  0.90  value >= 0.6  TRUE
# 8  0.25  value < 0.91  TRUE
# 9  0.04   value > 0.2 FALSE
``````

If you want to avoid `eval(parse...` you can try this:

``````library(tidyverse)
df %>% mutate(bound = as.numeric(str_extract(condition, "[0-9 \\.]*\$")),
goal = case_when(grepl("==", condition) ~ value == bound,
grepl(">=", condition) ~ value >= bound,
grepl("<=", condition) ~ value <= bound,
grepl(">", condition) ~ value > bound,
grepl("<", condition) ~ value < bound,
T ~ NA))

value     condition bound  goal
1  0.46   value > 0.5  0.50 FALSE
2  0.96 value == 0.79  0.79 FALSE
3  0.45 value <= 0.65  0.65  TRUE
4  0.68 value == 0.88  0.88 FALSE
5  0.57   value < 0.9  0.90  TRUE
6  0.10  value > 0.01  0.01  TRUE
7  0.90  value >= 0.6  0.60  TRUE
8  0.25  value < 0.91  0.91  TRUE
9  0.04   value > 0.2  0.20 FALSE
``````