knitr被data.table`:=`赋值 [英] knitr gets tricked by data.table `:=` assignment
问题描述
似乎 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 echo
ing 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 inknitr
for consistency with behaviour at the prompt, #505. Output of a testknit("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 noDT[]
before the end of the function, then the next timeDT
is typed at the prompt, nothing will be printed. A repeatedDT
will print. To avoid this: include aDT[]
after the last:=
in your function. If that is not possible (e.g., it's not a function you can change) thenprint(DT)
andDT[]
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 printsDT
. This implements #2128 "Try again to getDT[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屋!