假设我有一个数据集,并且我想使用管道语法对它应用几个过滤器,如下所示:
library(magrittr)
library(dplyr)
mtcars %<>%
filter(cyl == 4) %>%
select(cyl, mpg)
nrow(mtcars)
#[1] 11
我在每个这样的步骤之后用nrow
检查数据集的当前状态,所以我认为我可以按照
%<>%
运算符
`%<?>%` <- 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
现在通过打开或关闭pipeVerbose
标志,我将控制整个流程的跟踪程序。显然,由于内部评估机制,并不是那么简单,因为提示here。问题是,是否有可能以最小的努力实现所需的行为,即无需修补magittr
内部结构?
我不得不承认整个想法有点令人不安,但我的实际情况有点复杂,我想隐藏一些调试/开发细节,以便通过一个简单的开/关开关进行演示。
答案 0 :(得分:3)
您可以使用TaskCallback
,只要顶级任务完成就会执行。在回调检查中,表达式是否包含%<>%
运算符,如果是,则打印结果:
printAssignmentPipe <- function(exp, res, success, printed){
if (any(grepl("%<>%", exp, fixed = T))) {
print(res)
}
TRUE
}
addTaskCallback(printAssignmentPipe)
您可以轻松扩展回调以检查pipeVerbose
的值,或者只需致电addTaskCallback
和removeTaskCallback
即可激活/停用。
答案 1 :(得分:1)
由于链条利用了懒惰的评估,更好的翻译会是这样的:
`%<?>%` <- function(lhs, rhs) {
call <- match.call()
call[[1]] <- quote(`%<>%`)
x <- eval.parent(call)
if (is.data.frame(x) & pipeVerbose) print(nrow(x))
}
我们基本上重写函数调用并对其进行评估。
答案 2 :(得分:1)
请注意,您可以通过这种方式进行开/关切换,而不是使用%<?>%
代替%<>%
:
p <- function(x){if(pipeVerbose) print(nrow(x))}
pipeVerbose <- FALSE
mtcars %<>%
filter(cyl == 4) %>%
select(cyl, mpg) %T>% p
rm(mtcars)
pipeVerbose <- TRUE
mtcars %<>%
filter(cyl == 4) %>%
select(cyl, mpg) %T>% p