R Eval and Non-Standard Evaluation
eval() runs code that was held as data. A helper can run a caller's expression inside a data frame, so the caller writes the test in bare column names.
Run held code with eval
eval() runs the quoted addition at once and gives 5. The second call runs the multiplication with values taken from the list.
print(eval(quote(2 + 3)))
print(eval(quote(x * y), list(x = 3, y = 4)))Values come from a list
The list vals holds a and b. Each eval() call finds the names in the list and runs its expression there.
vals <- list(a = 10, b = 4)
print(eval(quote(a - b), vals))
print(eval(quote(a * b), vals))
print(eval(quote(a + b), vals))Filter a frame with a bare test
keep_rows() captures the test with substitute() and runs it inside the frame with eval(). The caller writes score > 80 with no frame prefix, and rows 1 and 3 pass.
df <- data.frame(name = c("Ana", "Bo", "Cy"), score = c(92, 70, 85))
keep_rows <- function(data, expr) {
keep <- eval(substitute(expr), data)
return(data[keep, ])
}
print(keep_rows(df, score > 80))A missing name stops eval
The list holds total but the expression names z. eval() cannot find z in the list, so the call stops with an error.
vals <- list(total = 10)
print(eval(quote(z + total), vals))Example
df <- data.frame(name = c("Ana", "Bo", "Cy", "Dee"), score = c(92, 70, 85, 64))
read_col <- function(data, col) {
return(eval(substitute(col), data))
}
keep_rows <- function(data, expr) {
keep <- eval(substitute(expr), data)
return(data[keep, ])
}
print(read_col(df, score))
print(keep_rows(df, score > 80))Key points
- eval() runs an expression that was held as data.
- A list or data frame passed to eval() gives the names in the expression their values.
- The pattern eval(substitute(expr), data) runs the caller's expression inside the data.
- A caller using that pattern writes column names bare, with no frame prefix.
- An expression that names a value the list does not hold stops with a not found error.
- This style of running a caller's expression against supplied values is called non-standard evaluation.
In this example, read_col() returns the score column by running the captured name inside the frame. keep_rows() then keeps the two rows where the score passes 80.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท rdrr.io R Snippets
Exercise
What does eval(quote(x * y), list(x = 3, y = 4)) print?