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?
knitr似乎不理解DT[, a:=1]不应该导致向文档输出DT。有办法阻止这种行为吗?
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?
这是一个knitr错误还是一个数据。表错误?
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
我刚刚注意到,knitr在回显代码时显得很奇怪。看看上面的输出。在源代码中我有DT[, c:=5]但是knitr渲染的是什么
DT[, `:=`(c, 5)]
Weird...
奇怪的……
EDIT 2: Caching
编辑2:缓存
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 `:=`?
缓存似乎也有一个与:=有关的问题,但这一定是另一个原因,这里有一个单独的问题:为什么knitr缓存对数据失败。表“:=”?
5 个解决方案
#1
19
Update Oct 2014. Now in data.table v1.9.5 :
更新2014年10月。现在的数据。表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.:=不再打印在knitr中,以保持提示符#505的行为一致性。测试编织(“knitr.Rmd”)的输出现在是数据。表的单元测试。
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][]
如果(真)DT[,LHS:=RHS]现在不能打印(感谢Jureiss, #869)。测试补充道。为了使它工作,我们必须忍受一个缺点:如果在函数结束前没有DT[]的函数中使用a:=,那么下次在提示符处输入DT时,将不会打印任何内容。重复的DT会打印出来。为了避免这一点:在函数中包含一个DT[]。如果这是不可能的(例如,它不是一个您可以更改的函数),那么在提示符上打印(DT)和DT[]将保证打印。如前所述,在a:=查询末尾添加一个额外的[]是一个推荐的用于更新和打印的习惯用法;例如> DT(foo:= 3 l)[]
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) ...
以前的答案是留给子孙后代的(全球$depthtrigger业务不再像从数据中那样执行。表v1.9.5因此这不再是正确的)…
Just to be clear I understand then: knitr
is printing when you don't want it to.
很明显,我明白了:当你不想要的时候,knitr正在印刷。
Try increasing data.table:::.global$depthtrigger
a little bit at the start of the script.
试着增加data.table:::。全局$depthtrigger在脚本的开头有一点。
This will be 3 for you currently :
这将是你目前的3:
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.
我不知道knitr为堆栈增加了多少eval depth值。但是先把触发器改成4;即。
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
在knitr脚本的末尾确保将其设置为3。如果4不行,试试5,然后6。如果你10岁就放弃,我会再考虑。- p;
Why might this work?
为什么这个工作?
See NEWS from v1.8.4 :
参见1.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.DT(lh:=,…不再打印DT。这实现了#2128“再次尝试获得DT[i,j:=value]返回不可见的”。感谢讨论:如何在使用“:=”时抑制输出。表},v1.8.3之前?http://r.789695.n4.nabble.com/Avoiding-print-when-using-tp4643076.html FAQs 2.21和2.22已经更新。
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).为什么DT[i,col:=value]返回整个DT?我希望没有可见的值(与<-)一致,或者是一个消息或返回值,其中包含有多少行被更新。不明显的是数据确实是通过引用更新的。这在v1.8.3中发生了变化,以满足您的期望。请升级。返回整个DT(现在是不可见的)以便复合语法可以工作;例如,DT(我做:= TRUE),sum(完成)。当在每个查询基础上或全局使用选项(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.FAQ 2.22好,谢谢。为什么不可见地返回DT[i,col:=value]的结果如此困难?内部强制能见度为[。FunTab's eval列的值(参见src/main/names.c)为[为0,表示force R_Visible on(参见R-Internals第1.6节)。因此,当我们尝试不可见()或直接将R_Visible设置为0时,在src/main/eval中使用eval。c会再次强迫它。要解决这个问题,关键是停止尝试停止在a:=之后运行的打印方法。相反,inside:= we now(从v1.8.3开始)设置了一个全局标记,打印方法使用该标记来知道是否实际打印。
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).
这个全局标志是data.table:: .global$print。表:::print.data。你会看到它在看着它。这是因为没有一种已知的方法可以抑制[(FAQ 2.22解释道)的打印。
So, inside :=
inside [.data.table
it looks to see how "deep" this call is :
那么,inside:= inside [.data]表中显示这个调用有多“深”:
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://*.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).
基本意思是:如果DT[,x:=y]在提示符处运行,那么我知道REPL将调用结果上的print方法,超出我的控制范围。好的,给定的print方法将要运行,我将通过设置一个标志(因为运行的print方法(例如print.data.table)是我可以控制的)来抑制它。
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
).
以knitr为例,它正在以一种巧妙的方式模拟REPL。它不是一个脚本,iiuc,否则DT[,x:=y]就不会打印。但是因为它是通过eval模拟REPL的,所以从knitr运行的代码有一个额外的eval depth值。或者类似的东西(我不知道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.
出租汽车司机/ crufty,我同意。但如果它有效,你让我知道哪个值有效,我可以改变数据。表要能识别并自动更改深度触发器。或者任何更好的解决方案都是最受欢迎的。
#2
7
Why not just use:
为什么不直接使用:
```{r, results='hide'}
DT[, c:=5]
```
#3
5
For anyone returning to this in 2017 with RMarkdown 1.3 and data.table 1.10 or similar, there was a resurgence of this bug, as identified and documented here
对于2017年拿着RMarkdown 1.3和数据回到这一目标的人来说。表1.10或类似的情况下,此错误再次出现,本文对此进行了标识和记录
This was subsequently fixed in RMarkdown 1.4
这在RMarkdown 1.4中得到了修正
#4
2
Just surround the expression with invisible(). This works for me.
只需用hidden()包围表达式。这适合我。
#5
1
I've run across the same problem and I solved it fairly easy by re-assigning the variable. In your case:
我遇到了同样的问题,通过重新分配变量,我很容易地解决了这个问题。在你的例子:
DT <- DT[, ':=' (c, 5)]
It's a bit more verbose though, especially if the variable name is big.
不过它有点冗长,特别是如果变量名很大的话。
#1
19
Update Oct 2014. Now in data.table v1.9.5 :
更新2014年10月。现在的数据。表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.:=不再打印在knitr中,以保持提示符#505的行为一致性。测试编织(“knitr.Rmd”)的输出现在是数据。表的单元测试。
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][]
如果(真)DT[,LHS:=RHS]现在不能打印(感谢Jureiss, #869)。测试补充道。为了使它工作,我们必须忍受一个缺点:如果在函数结束前没有DT[]的函数中使用a:=,那么下次在提示符处输入DT时,将不会打印任何内容。重复的DT会打印出来。为了避免这一点:在函数中包含一个DT[]。如果这是不可能的(例如,它不是一个您可以更改的函数),那么在提示符上打印(DT)和DT[]将保证打印。如前所述,在a:=查询末尾添加一个额外的[]是一个推荐的用于更新和打印的习惯用法;例如> DT(foo:= 3 l)[]
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) ...
以前的答案是留给子孙后代的(全球$depthtrigger业务不再像从数据中那样执行。表v1.9.5因此这不再是正确的)…
Just to be clear I understand then: knitr
is printing when you don't want it to.
很明显,我明白了:当你不想要的时候,knitr正在印刷。
Try increasing data.table:::.global$depthtrigger
a little bit at the start of the script.
试着增加data.table:::。全局$depthtrigger在脚本的开头有一点。
This will be 3 for you currently :
这将是你目前的3:
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.
我不知道knitr为堆栈增加了多少eval depth值。但是先把触发器改成4;即。
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
在knitr脚本的末尾确保将其设置为3。如果4不行,试试5,然后6。如果你10岁就放弃,我会再考虑。- p;
Why might this work?
为什么这个工作?
See NEWS from v1.8.4 :
参见1.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.DT(lh:=,…不再打印DT。这实现了#2128“再次尝试获得DT[i,j:=value]返回不可见的”。感谢讨论:如何在使用“:=”时抑制输出。表},v1.8.3之前?http://r.789695.n4.nabble.com/Avoiding-print-when-using-tp4643076.html FAQs 2.21和2.22已经更新。
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).为什么DT[i,col:=value]返回整个DT?我希望没有可见的值(与<-)一致,或者是一个消息或返回值,其中包含有多少行被更新。不明显的是数据确实是通过引用更新的。这在v1.8.3中发生了变化,以满足您的期望。请升级。返回整个DT(现在是不可见的)以便复合语法可以工作;例如,DT(我做:= TRUE),sum(完成)。当在每个查询基础上或全局使用选项(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.FAQ 2.22好,谢谢。为什么不可见地返回DT[i,col:=value]的结果如此困难?内部强制能见度为[。FunTab's eval列的值(参见src/main/names.c)为[为0,表示force R_Visible on(参见R-Internals第1.6节)。因此,当我们尝试不可见()或直接将R_Visible设置为0时,在src/main/eval中使用eval。c会再次强迫它。要解决这个问题,关键是停止尝试停止在a:=之后运行的打印方法。相反,inside:= we now(从v1.8.3开始)设置了一个全局标记,打印方法使用该标记来知道是否实际打印。
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).
这个全局标志是data.table:: .global$print。表:::print.data。你会看到它在看着它。这是因为没有一种已知的方法可以抑制[(FAQ 2.22解释道)的打印。
So, inside :=
inside [.data.table
it looks to see how "deep" this call is :
那么,inside:= inside [.data]表中显示这个调用有多“深”:
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://*.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).
基本意思是:如果DT[,x:=y]在提示符处运行,那么我知道REPL将调用结果上的print方法,超出我的控制范围。好的,给定的print方法将要运行,我将通过设置一个标志(因为运行的print方法(例如print.data.table)是我可以控制的)来抑制它。
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
).
以knitr为例,它正在以一种巧妙的方式模拟REPL。它不是一个脚本,iiuc,否则DT[,x:=y]就不会打印。但是因为它是通过eval模拟REPL的,所以从knitr运行的代码有一个额外的eval depth值。或者类似的东西(我不知道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.
出租汽车司机/ crufty,我同意。但如果它有效,你让我知道哪个值有效,我可以改变数据。表要能识别并自动更改深度触发器。或者任何更好的解决方案都是最受欢迎的。
#2
7
Why not just use:
为什么不直接使用:
```{r, results='hide'}
DT[, c:=5]
```
#3
5
For anyone returning to this in 2017 with RMarkdown 1.3 and data.table 1.10 or similar, there was a resurgence of this bug, as identified and documented here
对于2017年拿着RMarkdown 1.3和数据回到这一目标的人来说。表1.10或类似的情况下,此错误再次出现,本文对此进行了标识和记录
This was subsequently fixed in RMarkdown 1.4
这在RMarkdown 1.4中得到了修正
#4
2
Just surround the expression with invisible(). This works for me.
只需用hidden()包围表达式。这适合我。
#5
1
I've run across the same problem and I solved it fairly easy by re-assigning the variable. In your case:
我遇到了同样的问题,通过重新分配变量,我很容易地解决了这个问题。在你的例子:
DT <- DT[, ':=' (c, 5)]
It's a bit more verbose though, especially if the variable name is big.
不过它有点冗长,特别是如果变量名很大的话。