Dplyr's mutate
function can evaluate "chained" expressions, e.g.
library(dplyr)
data.frame(a = 1) %>%
mutate(b = a + 1, c = b * 2)
## a b c
## 1 1 2 4
How can this be implemented? Quick glance at dplyr's source code reveals the basic structure of the candidate code:
library(lazyeval)
library(rlang)
compat_as_lazy <- function(quo) {
structure(class = "lazy", list(
expr = f_rhs(quo),
env = f_env(quo)
))
}
compat_as_lazy_dots <- function(...) {
structure(class = "lazy_dots", lapply(quos(...), compat_as_lazy))
}
my_mutate <- function(.data, ...) {
lazy_eval(compat_as_lazy_dots(...), data = .data)
}
data.frame(a = 1) %>%
my_mutate(b = a + 1, c = b * 2)
## Error in eval(x$expr, data, x$env) : object 'b' not found
...but such "naive" implementation does not work and the C++ code behind mutate_impl
is pretty complicated. I understand that it doesn't work because lazy_eval
on "lazy_dots"
uses lapply
, i.e. each of the expressions is evaluated independently of each other, while I would rather need chained evaluation with returning the result back to the shared environment. How to make it work?
I'm not completely sure it's what you want but here are 3 mutate clones in base R that work with your example: