knitr被data.table`:=`赋值

时间:2013-03-07 09:08:23

标签: r data.table knitr

似乎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输出:

enter image description here

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

修改

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

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

...怪异

编辑2:缓存

缓存似乎也存在:=的问题,但这必须是一个不同的原因,因此这里有一个单独的问题:why does knitr caching fail for data.table `:=`?

5 个答案:

答案 0 :(得分:19)

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

  

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

及相关:

  

if (TRUE) DT[,LHS:=RHS]现在不打印(感谢Jureiss,#869)。测试补充。为了实现这一点,我们不得不忍受一个缺点:如果在函数结束之前在函数内部使用:=而没有DT[],那么下一次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;即。

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]无形地返回“。感谢此处的讨论:
  how to suppress output when using `:=` in R {data.table}, prior to v1.8.3?
  http://r.789695.n4.nabble.com/Avoiding-print-when-using-tp4643076.html
          常见问题解答2.21和2.22已更新。

     

FAQ 2.21为什么DT [i,col:= value]返回整个DT?我预计要么没有可见值(与&lt ;-)一致,要么是消息或返回   包含更新行数的值。这并不明显   数据确实已经通过引用进行了更新。
这在v1.8.3中有所改变   满足你的期望。请升级。返回整个DT   (现在看不见了)这样复合句法可以起作用;例如。,   DT [I,完成:= TRUE] [,总和(完成)]。返回更新的行数   当详细程度打开时,基于每个查询或全局使用   选项(datatable.verbose = TRUE)。

     

常见问题2.22好的,谢谢。 DT [i,col:= value]的结果难以置信地返回了什么?
R内部力量   能见度为[。 FunTab的eval列的值(参见   src / main / names.c)for [is 0表示强制R_Visible on(参见   R-Internals第1.6节)。因此,当我们尝试invisible()或   直接将R_Visible设置为0,在src / main / eval.c中设置为eval   会再强迫它。要解决这个问题,关键是要停下来   试图在:=后停止运行打印方法。相反,里面:=   我们现在(从v1.8.3开始)设置打印方法使用的全局标志   知道是否实际打印。

该全球旗帜为data.table:::.global$print。在data.table:::print.data.table的顶部,您会看到它正在查看它。那是因为没有已知的方法可以抑制[的打印(正如FAQ 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方法运行(即{{1})来在print方法中禁止它我可以控制的东西。)

print.data.table的情况下,它以聪明的方式模拟REPL。这不是一个真正的脚本,iiuc,否则knitr无论如何都不会打印出来。但是因为它通过DT[,x:=y]模拟REPL,所以从eval运行的代码有一个额外的eval深度级别。或类似的东西(我不知道knitr)。

这就是为什么我认为增加knitr可能会成功。

Hacky / crufty,我同意。但如果它有效,并且您让我知道哪个值有效,我可以将depthtrigger更改为data.table,并自动更改knitr。或者,欢迎任何更好的解决方案。

答案 1 :(得分:7)

为什么不使用:

```{r, results='hide'}
DT[, c:=5]
```

答案 2 :(得分:5)

对于2017年使用RMarkdown 1.3和data.table 1.10或类似内容返回此处的人,有一个resurgence of this bug, as identified and documented here

随后在RMarkdown 1.4中修复了

答案 3 :(得分:2)

用invisible()包围表达式。这对我有用。

答案 4 :(得分:1)

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

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

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