2017-07-21 153 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

相關問題