knitr被data.table`:=`赋值 [英] knitr gets tricked by data.table `:=` assignment

查看:125
本文介绍了knitr被data.table`:=`赋值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎 knitr 不明白 DT [,a:= 1] 到文档的输出 DT 。是否有办法阻止此行为?



示例 knitr 文档:



  Data.Table Markdown 
=========================== ===========================
假设我们在** R Markdown中创建一个`data.table` ** b $ b```{r}
DT = data.table(a = rnorm(10))
```
注意它不显示内容,直到我们做
```{r}
DT
```
style命令。但是,如果我们要使用`:=`来创建另一个列
```{r}
DT [,c:= 5]
```
似乎没有一个等号表示把knitr认为这个
是打印的。



Knitr输出:





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



/ strong>



我只是注意到, knitr 是很奇怪,当它 echo 输入代码。看看上面的输出。在我的源代码中,我有 DT [,c:= 5] knitr 呈现

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

很奇怪...



EDIT 2:缓存 b $ b

缓存似乎也有一个问题与:= 但是必须是不同的原因,所以是一个单独的问题在这里:为什么knitr缓存失败for data.table`:=`?

解决方案

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


:= knitr 与提示符处的行为保持一致,#505 < a>。输出测试 knit(knitr.Rmd)现在在data.table的单元测试中。


和相关:



<$> <$> 现在不打印(感谢Jureiss,
#869 )。测试已添加。为了让这个工作,我们不得不忍受一个缺点:如果:= 在没有 DT [] 在函数结束之前,然后下一次 DT 在提示符下键入,则不会打印任何内容。将打印重复的 DT 。为了避免这种情况:在函数中最后一个:= 之后加入 DT [] 如果这是不可能的(例如,它不是一个可以改变的函数),然后 print(DT) DT [] 在提示符下保证打印。和以前一样,在:= 查询的结尾添加一个额外的 [] 是更新的推荐习语打印;例如> DT [,foo:= 3L] []










以前的答案保存为后代( global $ depthtrigger 业务不再像data.table v1.9.5那样做不再是真的)...



只是为了清楚我明白了: knitr



尝试增加 data.table :::。global $ depthtrigger




$ b

$ c> data.table :::。global $ depthtrigger
[1] 3

我不知道多少eval depth knitr 添加到堆栈。但尝试将触发器改为4;即

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

并在 knitr 脚本的末尾确保将其设置为3。如果4不工作,请尝试5,然后6.如果你得到10放弃,我会再想想。 ; -P



为什么可能会有效?



查看News from 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已更新。



常见问题2.21为什么DT [i,col:= value]返回整个DT?我期望没有可见的值(与< ;-)一致,或者返回
值,其中包含更新了多少行。很明显
数据的确是通过引用更新的。

为了满足你的期望,v1.8.3
中的内容已经改变了。请升级。整个DT返回
(现在不可见),以便复合语法可以工作;例如
DT [i,done:= TRUE] [,sum(done)]。当详细程度打开时,在每个查询基础上或全局使用
选项(datatable.verbose = TRUE)时,更新的行数返回



常见问题2.22好,谢谢。关于DT [i,col:= value]被不可见地返回的结果如此困难?
R内部强制
可见性为[。 FunTab的eval列(参见
src / main / names.c)的值为0意味着强制R_Visible(参见
R-Internals第1.6节)。因此,当我们尝试invisible()或
设置R_Visible为0直接自己,eval在src / main / eval.c
将再次强制它。为了解决这个问题,关键是停止
试图停止打印方法后运行a:=。相反,里面:=
现在(从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 ){.global $ print = FALSE; x}
#拒绝打印,当返回确定不打开错误,错误#2376。
#感谢:http://stackoverflow.com/a/13606880/403310
#此后的所有适当返回都是
#wrapped即return(suppPrint(x))。
}

基本上只是说:if DT [,x := y] 正在运行的提示符,然后我知道REPL将调用打印方法在我的结果,超出了我的控制。好了,因此给定打印方法将要运行,我将通过设置在打印方法一个标志(因为运行的打印方法(即 print.data.table )是我可以控制的)。



knitr 的情况下,它以一种聪明的方式模拟REPL。它不是一个真正的脚本,iiuc,否则 DT [,x:= y] 将无法打印的原因。但是因为它通过 eval 模拟REPL,所以有一个额外的 eval 深度代码从 knitr 。或者类似的东西(我不知道 knitr )。



这是为什么我想增加 depthtrigger 可能会做的。



Hacky / crufty,我同意。但如果它工作,你让我知道哪个值工作,我可以更改 data.table knitr 意识并自动更改 depthtrigger 。或者任何更好的解决方案是最受欢迎的。


It seems that knitr doesn't understand that DT[, a:=1] should not result in an output of DT to the document. Is there a way to stop this behaviour?

Example knitr document:

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 Output:

Is this a knitr bug or a data.table bug?

EDIT

I have only just noticed, that knitr is being weird when it is echoing the code. Look at the output above. In my source code I have DT[, c:=5] but what knitr renders is

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

Weird...

EDIT 2: Caching

Caching also seems to have a problem with := but that must be a different cause, so is a separate question here: why does knitr caching fail for data.table `:=`?

解决方案

Update Oct 2014. Now in data.table v1.9.5 :

:= no longer prints in knitr for consistency with behaviour at the prompt, #505. Output of a test knit("knitr.Rmd") is now in data.table's unit tests.

and related :

if (TRUE) DT[,LHS:=RHS] now doesn't print (thanks to Jureiss, #869). Test added. To get this to work we've had to live with one downside: if a := is used inside a function with no DT[] before the end of the function, then the next time DT is typed at the prompt, nothing will be printed. A repeated DT will print. To avoid this: include a DT[] after the last := in your function. If that is not possible (e.g., it's not a function you can change) then print(DT) and DT[] at the prompt are guaranteed to print. As before, adding an extra [] on the end of a := query is a recommended idiom to update and then print; e.g. > DT[,foo:=3L][]



Previous answer kept for posterity (the global$depthtrigger business is no longer done as from data.table v1.9.5 so this is no longer true) ...

Just to be clear I understand then: knitr is printing when you don't want it to.

Try increasing data.table:::.global$depthtrigger a little bit at the start of the script.

This will be 3 for you currently :

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

I don't know how much eval depth knitr adds to the stack. But try changing the trigger to 4 first; i.e.

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

and at the end of the knitr script ensure to set it back to 3. If 4 doesn't work, try 5, then 6. If you get to 10 give up and I'll think again. ;-P

Why might this work?

See NEWS from v1.8.4 :

DT[,LHS:=RHS,...] no longer prints DT. This implements #2128 "Try again to get DT[i,j:=value] to return invisibly". Thanks to discussions here :
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
FAQs 2.21 and 2.22 have been updated.

FAQ 2.21 Why does DT[i,col:=value] return the whole of DT? I expected either no visible value (consistent with <-), or a message or return value containing how many rows were updated. It isn't obvious that the data has indeed been updated by reference.
This has changed in v1.8.3 to meet your expectations. Please upgrade. The whole of DT is returned (now invisibly) so that compound syntax can work; e.g., DT[i,done:=TRUE][,sum(done)]. The number of rows updated is returned when verbosity is on, either on a per query basis or globally using options(datatable.verbose=TRUE).

FAQ 2.22 Ok, thanks. What was so difficult about the result of DT[i,col:=value] being returned invisibly?
R internally forces visibility on for [. The value of FunTab's eval column (see src/main/names.c) for [ is 0 meaning force R_Visible on (see R-Internals section 1.6). Therefore, when we tried invisible() or setting R_Visible to 0 directly ourselves, eval in src/main/eval.c would force it on again. To solve this problem, the key was to stop trying to stop the print method running after a :=. Instead, inside := we now (from v1.8.3) set a global flag which the print method uses to know whether to actually print or not.

That global flag is data.table:::.global$print. At the top of data.table:::print.data.table you'll see it looking at it. That's because there is no known way to suppress printing from [ (as FAQ 2.22 explains).

So, inside := inside [.data.table it looks to see how "deep" this call is :

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: http://stackoverflow.com/a/13606880/403310
    # All appropriate returns following this point are
    # wrapped i.e. return(suppPrint(x)).
}

Essential that's just saying: if DT[,x:=y] is running at the prompt, then I know the REPL is going to call the print method on my result, beyond my control. Ok, so given print method is going to run, I'm going to suppress it inside that print method by setting a flag (since the print method that runs (i.e. print.data.table) is something I can control).

In knitr's case it's simulating the REPL in a clever way. It isn't really a script, iiuc, otherwise DT[,x:=y] wouldn't print anyway for that reason. But because it's simulating REPL via an eval there is an extra level of eval depth for code run from knitr. Or something similar (I don't know knitr).

Which is why I'm thinking increasing the depthtrigger might do the trick.

Hacky/crufty, I agree. But if it works, and you let me know which value works, I can change data.table to be knitr aware and change the depthtrigger automatically. Or any better solutions are most welcome.

这篇关于knitr被data.table`:=`赋值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆