为什么knitr缓存失败了data.table`:=`?

Cor*_*one 19 caching r knitr data.table

这在精神上与这个问题有关,但必须在机制上有所不同.

如果您尝试缓存knitr包含data.table :=分配的块,那么它就好像该块尚未运行,后来的块看不到该影响:=.

知道为什么会这样吗?knitr检测对象如何更新,以及如何data.table混淆它?

看起来你可以通过这样做来解决这个问题DT = DT[, LHS:=RHS].

示例:

```{r}
library(data.table)
```
Data.Table Markdown
========================================================
Suppose we make a `data.table` in **R Markdown**
```{r, cache=TRUE}
DT = data.table(a = rnorm(10))
```
Then add a column using `:=`
```{r, cache=TRUE}
DT[, c:=5] 
```
Then we display that in a non-cached block
```{r, cache=FALSE}
DT
```
The first time you run this, the above will show a `c` column, 
from the second time onwards it will not.
Run Code Online (Sandbox Code Playgroud)

第二轮输出

编织输出

Jos*_*ien 19

猜测:

这似乎是正在发生的事情.

knitr在创建对象时非常明智地缓存对象.然后,只要它检测到它们已被更改,它就会更新它们的缓存值.

data.table,虽然绕过的r普通副本按值分配和更换机制,并采用了:=运营商,而不是=,<<-或<-.结果knitr没有拾取DT已被改变的信号DT[, c:=5].

解:

只需将此块添加到您希望DT重新缓存当前值的代码中.它不会花你一分钱内存或时间明智的(因为没有除了参考被复制DT <- DT),但它确实有效地发送一个(假的)信号knitr这DT已更新:

```{r, cache=TRUE, echo=FALSE}
DT <- DT 
```
Run Code Online (Sandbox Code Playgroud)

示例文档的工作版本:

通过运行此doc的编辑版本来检查它是否有效:

```{r}
library(data.table)
```
Data.Table Markdown
========================================================
Suppose we make a `data.table` in **R Markdown**
```{r, cache=TRUE}
DT = data.table(a = rnorm(10))
```

Then add a column using `:=`
```{r, cache=TRUE}
DT[, c:=5] 
```

```{r, cache=TRUE, echo=FALSE}
DT <- DT 
```

Then we display that in a non-cached block
```{r, cache=FALSE}
DT
```
The first time you run this, the above will show a `c` column. 
The second, third, and nth times, it will as well.
Run Code Online (Sandbox Code Playgroud)

  • @Corone在这种情况下,手动将对象名称分配给`knitr`来缓存是个好主意; 如果您提交功能请求,我可以考虑一下:https://github.com/yihui/knitr/issues (3认同)
  • @MatthewDowle - 这样的东西应该有效:``%"%in sapply(sys.calls(),function(X)deparse(X [[1]]))`.(在调用栈中搜索`evaluate`的调用可能比查找`knit`更安全,因为在`编程'的编译'编程'的情况下它会更好地工作,就像`do.call(编织,...)`或`sapply(...,knit)`等等) (2认同)

Yih*_*Xie 11

正如Josh O'Brien在答案中的第四条评论所示,我添加了一个新的块选项cache.vars来处理这个非常特殊的情况.在第二个缓存的块中,我们可以指定cache.vars='DT'以便knitr保存副本DT.

```{r}
library(data.table)
```
Data.Table Markdown
========================================================
Suppose we make a `data.table` in **R Markdown**
```{r, cache=TRUE}
DT = data.table(a = rnorm(10))
```
Then add a column using `:=`
```{r, cache=TRUE, cache.vars='DT'}
DT[, c:=5] 
```
Then we display that in a non-cached block
```{r, cache=FALSE}
DT
```
Run Code Online (Sandbox Code Playgroud)

无论编译文档多少次,输出都是这样的:

knitr现在可以使用data.table了