39

似乎knitr不明白这不DT[, a:=1]应该导致DT文档的输出。有没有办法阻止这种行为?

示例knitr文档:

Data.Table Markdown
========================================================
Suppose we make a `data.table` in **R Markdown**
```{r}
DT = data.table(a = rnorm(10))
```
Notice that it doesn't display the contents until we do a
```{r}
DT
```
style command.  However, if we want to use `:=` to create another column
```{r}
DT[, c:=5]
```
It would appear that the absence of a equals sign tricks `knitr` into thinking this 
is to be printed.

针织输出:

在此处输入图像描述

这是一个knitr错误还是一个data.table错误?

编辑

我刚刚注意到,在编写代码knitr时这很奇怪。echo看看上面的输出。在我的源代码中,我有DT[, c:=5],但knitr呈现的是

DT[, `:=`(c, 5)]

奇怪的...

编辑 2:缓存

缓存似乎也有问题,:=但这一定是另一个原因,所以这里有一个单独的问题:为什么 knitr 缓存对 data.table `:=` 失败?

4

5 回答 5

20

2014 年 10 月更新。现在在 data.table v1.9.5 中:

:=不再打印以与提示#505knitr处的行为保持一致。测试的输出现在在 data.table 的单元测试中。knit("knitr.Rmd")

和相关:

if (TRUE) DT[,LHS:=RHS]现在不打印(感谢 Jureiss,#869)。添加了测试。为了让它工作,我们不得不忍受一个缺点:如果:=在函数内部使用 a 并且在函数DT[]结束之前没有 no ,那么下次DT在提示符下键入,不会打印任何内容。重复DT将打印。为避免这种情况:在函数DT[]的最后一个之后包含一个。:=如果这是不可能的(例如,它不是您可以更改的功能)print(DT),那么DT[]保证在提示时打印。[]和以前一样,在查询末尾添加额外的内容:=是更新然后打印的推荐习惯用法;例如> DT[,foo:=3L][]



以前的答案留给后代(global$depthtrigger业务不再从 data.table v1.9.5 开始,所以这不再是真的)......

为了清楚起见,我明白了:knitr在你不想要的时候打印。

尝试data.table:::.global$depthtrigger在脚本开始时增加一点。

目前这将是 3 个:

data.table:::.global$depthtrigger
[1] 3

我不知道 eval 深度knitr增加了多少堆栈。但是先尝试将触发器更改为 4;IE

assign("depthtrigger", 4, data.table:::.global)

并在knitr脚本结束时确保将其设置回 3。如果 4 不起作用,请尝试 5,然后尝试 6。如果达到 10,请放弃,我会再考虑。;-P

为什么这行得通?

请参阅 v1.8.4 的新闻:

DT[,LHS:=RHS,...]不再打印DT。这实现了#2128“再次尝试DT[i,j:=value]以隐形返回”。感谢此处的讨论:
在 v1.8.3 之前,如何在 R {data.table} 中使用 `:=` 时抑制输出?
http://r.789695.n4.nabble.com/Avoiding-print-when-using-tp4643076.html
常见问题解答 2.21 和 2.22 已更新。

FAQ 2.21 为什么 DT[i,col:=value] 返回整个 DT?我期望要么没有可见值(与 <- 一致),要么是包含更新了多少行的消息或返回值。数据确实已通过引用进行更新并不明显。
这在 v1.8.3 中已更改以满足您的期望。请升级。整个 DT 被返回(现在是不可见的)以便复合语法可以工作;例如,DT[i,done:=TRUE][,sum(done)]。当详细程度打开时,将返回更新的行数,无论是基于每个查询还是全局使用选项(datatable.verbose=TRUE)。

FAQ 2.22 好的,谢谢。不可见地返回 DT[i,col:=value] 的结果有什么困难?
R 在内部强制为 [. FunTab 的 eval 列(参见 src/main/names.c)的值为 [ 是 0 表示强制 R_Visible on(参见 R-Internals 部分 1.6)。因此,当我们自己尝试 invisible() 或直接将 R_Visible 设置为 0 时, src/main/eval.c 中的 eval 会再次强制它打开。要解决这个问题,关键是在 := 之后停止尝试停止 print 方法的运行。相反,我们现在(从 v1.8.3 开始)在 := 内部设置了一个全局标志,打印方法使用它来知道是否实际打印。

那个全局标志是data.table:::.global$print. 在顶部data.table:::print.data.table你会看到它在看它。那是因为没有已知的方法来抑制打印[(如常见问题解答 2.22 所述)。

所以,在:=里面[.data.table它看起来看看这个调用有多“深”:

if (Cstack_info()[["eval_depth"]] <= .global$depthtrigger) {
    suppPrint = function(x) { .global$print=FALSE; x }
    # Suppress print when returns ok not on error, bug #2376.
    # Thanks to: https://stackoverflow.com/a/13606880/403310
    # All appropriate returns following this point are
    # wrapped i.e. return(suppPrint(x)).
}

基本就是说:如果DT[,x:=y]在提示符下运行,那么我知道 REPL 将在我的结果上调用该print方法,这是我无法控制的。好的,所以给定print的方法将要运行,我将print通过设置一个标志在该方法中抑制它(因为print运行的方法(即print.data.table)是我可以控制的)。

knitr这种情况下,它以一种巧妙的方式模拟 REPL。这不是一个真正的脚本,iiuc,否则DT[,x:=y]无论如何都不会因为这个原因打印出来。但是因为它是通过模拟 REPL 的,eval所以evalknitr. 或类似的东西(我不知道knitr)。

这就是为什么我认为增加depthtrigger可能会起作用的原因。

哈克/粗鲁,我同意。但是,如果它有效,并且您让我知道哪个值有效,我可以更改data.tableknitr意识到并depthtrigger自动更改。或者任何更好的解决方案都是最受欢迎的。

于 2013-03-07T10:13:22.490 回答
7

为什么不直接使用:

```{r, results='hide'}
DT[, c:=5]
```
于 2014-08-19T19:49:34.410 回答
5

对于在 2017 年使用 RMarkdown 1.3 和 data.table 1.10 或类似版本返回此问题的任何人,此错误再次出现,如在此处确定和记录的那样

这随后在 RMarkdown 1.4 中得到修复

于 2017-04-05T10:28:14.863 回答
2

只需用 invisible() 将表达式括起来。这对我有用。

于 2015-05-09T08:17:16.307 回答
1

我遇到了同样的问题,我通过重新分配变量相当容易地解决了这个问题。在你的情况下:

DT <- DT[, ':=' (c, 5)]

虽然它有点冗长,特别是如果变量名很大。

于 2014-06-20T10:55:02.400 回答