Say I have a data set and I'd like to apply several filters to it using piping syntax, like so:
library(magrittr)
library(dplyr)
mtcars %<>%
filter(cyl == 4) %>%
select(cyl, mpg)
nrow(mtcars)
#[1] 11
I check the current status of the data set with nrow after each such step, so I thought I could override the piping %<>% operator along the lines of
`%<?>%` <- function(lhs, rhs) {
x <- magrittr::`%<>%`(lhs, rhs)
if (is.data.frame(x) & pipeVerbose) print(nrow(x))
}
#Using this will generate errors like
#Error in pipes[[i]] : subscript out of bounds
And now by switching pipeVerbose flag on or off I would control the tracking procedure for the whole flow. Apparently it's not that simple because of the internal evaluation mechanism, as prompted here. The question is, is it possible to achieve the desired behavior with minimal effort, i.e. without patching the magittr internals?
I have to admit the whole idea is slightly unsettling, but my actual scenario is a bit more complicated and I'd like to hide some debug/development details for demonstration purposes via a simple on/off switch.
You could make use of a TaskCallback which executes whenever a toplevel task is completed. In the callback check if the expression contains the %<>% operator and if yes print the result:
printAssignmentPipe <- function(exp, res, success, printed){
if (any(grepl("%<>%", exp, fixed = T))) {
print(res)
}
TRUE
}
addTaskCallback(printAssignmentPipe)
You can easily extend the callback to also check the value of pipeVerbose or you simply call addTaskCallback and removeTaskCallback to activate/deactivate.
Since chains take advantage of lazy evaluation, a better translation would have been something like this:
`%<?>%` <- function(lhs, rhs) {
call <- match.call()
call[[1]] <- quote(`%<>%`)
x <- eval.parent(call)
if (is.data.frame(x) & pipeVerbose) print(nrow(x))
}
We basically re-write the function call and evaluate it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With