编织R markdown文件时,我常常发现自己盯着Markdown输出等待一个块完成。不幸的是,我不知道有什么方法可以看到该块正在执行的命令。这对于了解进度或找到性能瓶颈非常方便。
我错过了一些针织选项吗?设置progress=TRUE, verbose=TRUE
只显示执行该块之前的块代码。我希望每行代码都在执行之后/之前显示在控制台中,就像在交互式会话中一样。
答案 0 :(得分:2)
在底部的控制台标签旁边,您会看到 R Markdown 标签,所有步骤都可以在那里看到,请参见下面的屏幕截图:
编辑1:我们需要设置全局选项opts_knit$set(progress = TRUE, verbose = TRUE)
示例:
---
title: "Untitled"
output: html_document
---
```{r global_options, include=FALSE}
library(knitr)
opts_knit$set(progress = TRUE, verbose = TRUE)
```
This is an R Markdown document. Markdown is a simple ...
```{r SummaryCars}
summary(cars)
```
R Markdown 窗口的输出:
processing file: temppp.Rmd
|................ | 25%
ordinary text without R code
|................................ | 50%
label: global_options (with options)
List of 1
$ include: logi FALSE
|................................................. | 75%
ordinary text without R code
|.................................................................| 100%
label: SummaryCars
~~~~~~~~~~~~~~~~~~~~~~~~~ R code chunk ~~~~~~~~~~~~~~~~~~~~~~~~~~
summary(cars)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
##------ Fri Jul 17 09:00:42 2015 ------##
output file: temppp.knit.md
编辑2:这个答案不符合OP的要求,以此答案为例说明OP的代码。
答案 1 :(得分:0)
这是一个解决方案... 但:极其谨慎地使用它。在评估之前,它会对源代码感到困惑。此外,它使输出文档与诊断输出混乱。但是,出于调试目的,它可能非常有用。
据我了解,RStudio中编织过程的进度窗口不能用于记录块的评估进度,因为任何块输出(如message
s)仅在整个块之后显示评估。因此,唯一可行的解决方法是将进度写入文件。
因此,解决方案是编写一些诊断消息,例如"现在评估[code]
"到文件,表达式表达。不幸的是,在每个表达式"之前,没有默认的knitr hook用于"调用FUN
。块中的所有代码(至少是要评估的所有代码)都传递到evaluate::evaluate
中的block_exec
(请参阅line 172 in block.R
)。
由于knitr永远不会通过表达式迭代一个块的代码表达式,因此没有自然的方法来植入写入诊断消息的逻辑。 (我没有深入研究evaluate
;也许这样的迭代发生在其中的某个地方。)然而,在传递之前,可以操作块的源代码马上到evaluate
。
请注意,运行块时,其源代码可用作chunk option code
的值。结构是一个字符向量,每个元素代表一行。操作code
允许修改源代码,以便在评估时自己编写诊断消息。
我将使用以下小助手函数来编写日志文件:
writeLog <- function(message, file = paste0(current_input(), ".log"), sep = "\n") {
cat(paste(message, sep), file = file, append = TRUE)
}
日志文件的文件名将为[documentname].log
,例如mydocument.Rmd.log
。由于writeLog
始终附加到现有文件,因此以下行可用于清除(擦除和重新创建)每个编译的日志文件:
if(file.exists(logfile <- paste0(current_input(), ".log"))) { file.remove(logfile) }
writeLog
的潜在有用扩展可以gc()
使用monitor the memory usage。
基本思想是添加类似
的内容writeLog(sprintf("%s - Now evaluating the following expression: ", format(Sys.time(), "%Y-%m-%d %H:%M:%S")), sep = NULL)
writeLog('summary(cars)')
在每个表达式之前(在上面的例子中:summary(cars)
之前)。问题是,到位writeLog
的确切位置应该在哪里?对于每行只包含一个(完整)表达式的代码,这不是问题,但在以下情况下 有问题:
summary( # Here some descriptives:
cars
)
对于具有该代码的块,code
将是具有三个元素的向量:
print(code)
[1] "summary( # Here some descriptives:" " cars" ")"
在每个元素不之后简单地注入writeLog
个调用是个好主意...因此,这就是解决方案变得有些讨厌的地方,code
需要{{1}首先。使用参数parse
,所有注释,格式等都将被删除,我们得到&#34; clean&#34;表达式。
在每个表达式之前,可以插入keep.source = FALSE
个调用。此新代码使用我调用writeLog
的{{3}}替换原始代码:
log
从以下块开始
opts_hooks$set(log = function(options) {
parsed <- parse(text = options$code, keep.source = FALSE)
newCode <- sapply(as.character(parsed), function(x) {
return(c(
'writeLog(sprintf("%s - Now evaluating the following expression: ", format(Sys.time(), "%Y-%m-%d %H:%M:%S")), sep = NULL)',
sprintf("writeLog('%s')", x),
x))
})
options$code = as.vector(newCode)
return(options)
})
源代码变为
```{r, log = TRUE}
summary( # Here some descriptives
cars
)
Sys.sleep(5)
print("foo")
```
生成以下日志文件:
writeLog(sprintf("%s - Now evaluating the following expression: ", format(Sys.time(), "%Y-%m-%d %H:%M:%S")), sep = NULL)
writeLog('summary(cars)')
summary(cars)
writeLog(sprintf("%s - Now evaluating the following expression: ", format(Sys.time(), "%Y-%m-%d %H:%M:%S")), sep = NULL)
writeLog('Sys.sleep(5)')
Sys.sleep(5)
writeLog(sprintf("%s - Now evaluating the following expression: ", format(Sys.time(), "%Y-%m-%d %H:%M:%S")), sep = NULL)
writeLog('print("foo")')
print("foo")
由于日志文件的目的是在编织过程中反映进度,因此在不阻止对其进行进一步写入操作的情况下打开它是很重要的。理想情况下,我们甚至希望看到文件的更新。
在Windows上,例如Notepad ++以非阻塞方式打开文件,并有option hook选项。在Linux上,2016-03-04 12:08:05 - Now evaluating the following expression: summary(cars)
2016-03-04 12:08:05 - Now evaluating the following expression: Sys.sleep(5)
2016-03-04 12:08:10 - Now evaluating the following expression: print("foo")
autoreload modified files。
主要限制与输出文档中可见的源代码有关tail -f [documentname].log
:它被echo = TRUE
调用污染。此外,所有评论和标识都丢失了,语法是标准化的#34; (例如,writeLog
变为print('x')
)。到目前为止,我还没有找到解决方案 - 只有部分解决方案:
print("x")
添加为options$codeBackup <- options$code
选项挂钩中的第一行。使用should do the trick log
并将参数source
(将打印的源代码)替换为x
:
options$codeBackup
hook_source <- knit_hooks$get("source")
knit_hooks$set(source = function(x, options) {
return(hook_source(options$codeBackup, options))
})
或块,其中唯一的输出发生在最后。否则,只要打印代码的部分,完整的代码就会重复。此外,操纵源代码可能很危险。由于results = "keep"
是一个基本R函数,我不希望解析本身存在问题。但是,我不确定之后转换为角色。
更令人担忧的是将函数调用插入到原始源中。本身,parse
非常有创意,不应干扰以下代码。但你永远不知道。想象一段代码生成当前工作目录(第一个表达式)中所有文件的列表,并依赖此列表在第二个表达式中准确。突然之间,在中间创建日志文件已经不再那么无辜了......(即使这个例子中的真正问题又回到了原始代码中的output hook)。
底线是:不要在生产中使用此代码&#34;&#34;但仅用于调试目的。
writeLog