Подтвердить что ты не робот

Почему кэширование 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.

Выход во втором запуске

knitr output

4b9b3361

Ответ 1

Спекуляция:

Вот что происходит.

knitr довольно разумно кэширует объекты, как только они создаются. Затем он обновляет свои кешированные значения, когда обнаруживает, что они были изменены.

data.table, однако, обходит R нормальные механизмы присваивания и замены по умолчанию и использует оператор :=, а не =, <<- или <-. В результате knitr не подбирает сигналы, которые DT были изменены на DT[, c:=5].

Решение:

Просто добавьте этот блок в свой код, где бы вы не захотели повторно кэшировать текущее значение DT. Это не будет стоить вам какой-либо памяти или по времени (поскольку ничего, кроме ссылки, не копируется с помощью DT <- DT), но эффективно отправляет (поддельный) сигнал на knitr, который DT был обновление:

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

Рабочая версия примера 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.

Ответ 2

Как указано в четвертом комментарии в ответе Джоша О'Брайена, я добавил новую опцию 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
```

Результат такой, независимо от того, сколько раз вы компилируете документ:

knitr works with data.table now