在长管道中间打印消息

Ahm*_*bas 6 r pipe dplyr magrittr tidyverse

在我的 R 脚本中,我想在长管道中间打印一条消息(需要很长时间才能运行)而不破坏管道。我需要它来跟踪正在运行的管道的进度。

我尝试创建一个简单的函数,可以在不破坏管道的情况下打印消息:

CatPipe <- function(x, message = NULL) {
  cat(message, sep = "\n")
  return(x)
}
Run Code Online (Sandbox Code Playgroud)

这是一个示例实现:

require(dplyr)
mtcars %>% 
  CatPipe("Hello1") %>% 
  {
    Sys.sleep(1)
    .
  } %>% 
  CatPipe("Hello2") %>% 
  {
    Sys.sleep(1)
    .
     } %>% 
    head(5) %>% 
    CatPipe("Hello3")
Run Code Online (Sandbox Code Playgroud)

然而,打印的消息并不如预期。无论当前步骤是否完成,消息都会以相反的顺序打印!

Hello3
Hello2
Hello1
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Run Code Online (Sandbox Code Playgroud)

对此有解释吗?我应该对该功能进行任何更改吗?是否有使用dplyr、magrittr或类似包的替代方案?

Ben*_*ker 9

该%>%管道使用惰性求值,这意味着它在需要时才求值表达式。实际上,这意味着它到达管道的末端magrittr,然后向后工作...该包定义了一个急切的管道运算符%!>%,它具有您想要的行为(%>%实际上也来自magrittr;它是由dplyr)。

\n

为了打印mtcars之前的输出Hello3,您可以使用三通管(%T>%),也来自magrittr,加上一条print()语句。输出通常在最后打印的原因是,R 仅在表达式完全求值后才打印其最终结果。(我还在-> result管道的末尾添加了一个来存储结果并防止在末尾再次打印它;我添加了一个SleepPipe()与您类似的函数CatPipe()以使代码更漂亮。)

\n
library(magrittr)\nSleepPipe <- function(x, time = 1) {\n    Sys.sleep(time)\n    return(x)\n}\nmtcars %!>% \n  CatPipe("Hello1") %!>% \n  SleepPipe(1) %!>% \n  CatPipe("Hello2") %!>% \n  SleepPipe(1) %!>%\n  head(5) %T>% print() %!>% \n  CatPipe("Hello3") -> result\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 我不能保证从懒惰评估变为急切评估不会在复杂的管道中产生其他副作用
  • \n
  • 本机-R 管道|>还使用惰性求值(为了测试它,我必须使用该SleepPipe()函数,因为本机管道不允许任意{.}表达式)
  • \n
  • FWIW R for Data Science与这个答案相矛盾:它说使用惰性求值的函数在管道工作流中不起作用,因为“管道依次计算每个元素,所以你可以\xe2\x80\x99t依赖这种行为”。我认为这是因为magrittr 在 2.0 版本中重新实现了管道以使用惰性求值....
  • \n
\n