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

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

问题描述

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

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?

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 错误?

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

编辑

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

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)]

奇怪...

编辑 2:缓存

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

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 `:=`?

推荐答案

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

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

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

:= 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.

及相关:

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

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][]

<小时><小时>

为后代保留以前的答案(global$depthtrigger 业务不再像 data.table v1.9.5 那样完成,因此不再适用)...



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) ...

为了清楚起见,我明白了:knitr 正在打印,而您不希望它打印.

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

尝试在脚本开始时稍微增加 data.table:::.global$depthtrigger.

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

目前这将是 3 个:

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

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

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)

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

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

为什么会这样?

查看 v1.8.4 的新闻:

See NEWS from v1.8.4 :

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

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

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

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.

那个全局标志是 data.table:::.global$print.在 data.table:::print.data.table 的顶部,您会看到它正在查看它.这是因为没有已知的方法来禁止从 [ 打印(如常见问题解答 2.22 所述).

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 内部的 := 中,它看起来会看到这个调用有多深度":

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: 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)是我可以控制的).

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).

knitr 的例子中,它以一种巧妙的方式模拟了 REPL.它不是真正的脚本,iiuc,否则 DT[,x:=y] 无论如何都不会因为这个原因打印.但是因为它是通过 eval 模拟 REPL,所以对于从 knitr 运行的代码,会有一个额外的 eval 深度.或类似的东西(我不知道 knitr).

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).

这就是为什么我认为增加 depthtrigger 可能会奏效.

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

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

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天全站免登陆