2017-07-21 68 views
2

说我有一个数据集,我想使用管道语法几个过滤器适用于它,像这样:如何重写magrittr管道运算符?

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。问题是,是否有可能以最小的努力达到所需的行为,即不修补内部零件?

我不得不承认整个想法有点令人不安,但是我的实际情况稍微复杂一点,我想通过一个简单的开/关开关隐藏一些调试/开发细节用于演示目的。

+0

如果我没有理解好了,你想打印的nrow在输出管道的每一步? –

+0

@ColinFAY不完全;只有在使用'%<>%'进行重新分配时才会发生,并且无需在每个地方添加额外的管道步骤,如'%>%nrow'。 – tonytonov

+1

可能相关:[rmonad](https://cran.r-project.org/web/packages/rmonad/index.html) –

回答

1

由于链利用懒惰的评价,更好的翻译将是这样的:

`%<?>%` <- function(lhs, rhs) { 
    call <- match.call() 
    call[[1]] <- quote(`%<>%`) 
    x <- eval.parent(call) 
    if (is.data.frame(x) & pipeVerbose) print(nrow(x)) 
} 

我们基本上是重新编写的函数调用,并对其进行评估。

3

您可以使用TaskCallback,该任务在顶层任务完成时执行。在回调检查如果表达式包含%<>%操作,如果是打印出结果:

printAssignmentPipe <- function(exp, res, success, printed){ 

    if (any(grepl("%<>%", exp, fixed = T))) { 
    print(res) 
    } 
    TRUE 
} 

addTaskCallback(printAssignmentPipe) 

您可以轻松地扩展回调也检查pipeVerbose值,或者您只需拨打addTaskCallbackremoveTaskCallback激活/停用。

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 
+0

谢谢;这与我最终达成的目标非常接近。 – tonytonov

相关问题