在长管道中间打印消息

Print message in the middle of long pipe

提问人:Ahmed El-Gabbas 提问时间:7/19/2023 最后编辑:Ben BolkerAhmed El-Gabbas 更新时间:7/20/2023 访问量:79

问:

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

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

CatPipe <- function(x, message = NULL) {
  cat(message, sep = "\n")
  return(x)
}

下面是一个示例实现:

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

但是,打印的消息与预期不符。消息以相反的顺序打印,无论当前步骤是否完成!

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

对此有解释吗?我应该对函数进行任何更改吗?有没有使用 、 或类似包的替代方案?dplyrmagrittr

R dplyr 管道 Tidyverse Magrittr

评论


答:

9赞 Ben Bolker 7/19/2023 #1

管道使用延迟计算,这意味着它不会计算表达式,直到需要。在实践中,这意味着它到达管道的末端,然后向后工作......该包定义了一个 eager pipe 运算符,它具有您想要的行为(实际上也来自 ;它由 导入和重新导出)。%>%magrittr%!>%%>%magrittrdplyr

为了打印输出之前,您可以使用三通管(),也可以从,加上语句。输出通常在末尾打印的原因是,R 仅在表达式被完全计算后才打印表达式的最终结果。(我还在管道的末端添加了一个来存储结果并防止它在最后再次打印;我添加了一个类似于你的函数,使代码更漂亮一点。mtcarsHello3%T>%magrittrprint()-> resultSleepPipe()CatPipe()

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

评论

0赞 Ahmed El-Gabbas 7/20/2023
我不知道存在一个急切的管道。谢谢本。我在这里阅读更多关于这方面的信息:magrittr.tidyverse.org/reference/pipe-eager.html。我尝试在函数中使用,但这不起作用。它在管道结束后一起显示所有消息。force(x)