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

Knitr получает обманутые data.table `: =` назначение

Кажется, что knitr не понимает, что DT[, a:=1] не должен приводить к выходу DT в документ. Есть ли способ остановить это поведение?

Пример 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.

Выход ножей:

enter image description here

Является ли это ошибкой knitr или ошибкой data.table?

ИЗМЕНИТЬ

Я только что заметил, что knitr является странным, когда он echo вводит код. Посмотрите на вышеприведенный результат. В моем исходном коде у меня есть DT[, c:=5], но что knitr отображает

DT[, `:=`(c, 5)]

Weird...

РЕДАКТИРОВАТЬ 2: Кэширование

Кэширование также, по-видимому, имеет проблему с :=, но это должно быть другой причиной, поэтому здесь возникает отдельный вопрос: почему кеш-кэп не работает для data.table`: = `?

4b9b3361

Ответ 1

Обновление Oct 2014. Теперь в data.table v1.9.5:

:= больше не печатает в knitr для согласованности с поведением в приглашении, # 505. Вывод теста knit("knitr.Rmd") теперь находится в модульных тестах data.table.

и связанных с ним:

if (TRUE) DT[,LHS:=RHS] теперь не печатает (спасибо Jureiss, # 869). Добавлен тест. Чтобы это сработало, нам пришлось жить с одним недостатком: если := используется внутри функции без DT[] до конца функции, то в следующий раз DT вводится в приглашении, ничего не будет напечатано. Повторится DT. Чтобы избежать этого: включите DT[] после последнего := в вашу функцию. Если это невозможно (например, это не функция, которую вы можете изменить), то print(DT) и DT[] в приглашении гарантированно будут печататься. Как и прежде, добавление дополнительного [] в конец запроса := является рекомендуемой идиомой для обновления, а затем для печати; например > DT[,foo:=3L][]



Предыдущий ответ сохраняется для потомков (бизнес global$depthtrigger больше не выполняется, как из data.table v1.9.5, так что это уже не так)...

Чтобы быть ясным, я понимаю: knitr печатает, когда вы этого не хотите.

Попробуйте увеличить data.table:::.global$depthtrigger немного в начале script.

В данный момент это будет 3:

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

Я не знаю, насколько большая глубина eval knitr добавляется в стек. Но сначала попробуйте сменить триггер на 4; то есть.

assign("depthtrigger", 4, data.table:::.global)

и в конце knitr script убедитесь, что он установлен на 3. Если 4 не работает, попробуйте 5, затем 6. Если вы доберетесь до 10, сдайте, и я снова подумаю.;-P

Почему это может работать?

См. НОВОСТИ от 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 были обновлены.

Часто задаваемые вопросы 2.21 Почему DT [i, col: = значение] возвращает весь DT? Я ожидал, что ни видимое значение (согласующееся с <-), или сообщение или возврат значение, содержащее сколько строк было обновлено. Не очевидно, что данные действительно обновлены по ссылке.
Это изменилось в версии 1.8.3 чтобы оправдать ваши ожидания. Пожалуйста, обновите. Возвращается весь DT (теперь невидимо), так что сложный синтаксис может работать; например., DT [я, сделано: = TRUE] [, сумма (сделано)]. Возвращается количество обновленных строк когда многословие включено, либо для каждого запроса, либо для глобального использования Варианты (datatable.verbose = TRUE).

FAQ 2.22 Хорошо, спасибо. Что было так сложно в том, что результат DT [i, col: = value] возвращается невидимо?
R внутренние силы видимость на для [. Значение столбца FunTab eval (см. src/main/names.c) для [равно 0 означает силу R_Visible on (см. R-Internals, раздел 1.6). Поэтому, когда мы пробовали невидимый() или непосредственно установить R_Visible на 0, eval в src/main/eval.c снова заставит его. Чтобы решить эту проблему, ключ должен был остановить пытаясь остановить метод печати, выполняемый после: =. Вместо этого внутри: = мы теперь (из 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(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)).
}

Существенно, что просто говоря: if DT[,x:=y] работает в приглашении, тогда я знаю, что REPL собирается вызвать метод print по моему результату, вне моего контроля. Хорошо, поэтому данный метод print будет запущен, я собираюсь подавить его внутри этого метода print, установив флаг (поскольку метод print, который работает (т.е. print.data.table), я могу контролировать).

В knitr случае он имитирует REPL умным способом. Это не действительно script, iiuc, иначе DT[,x:=y] не будет печатать в любом случае по этой причине. Но поскольку он моделирует REPL через eval, существует дополнительный уровень глубины eval для запуска кода из knitr. Или что-то подобное (я не знаю knitr).

Вот почему я думаю, что увеличение depthtrigger может сделать трюк.

Хакки/жестокость, я согласен. Но если он работает, и вы даете мне знать, какое значение работает, я могу изменить data.table как knitr и автоматически изменить depthtrigger. Или любые лучшие решения приветствуются.

Ответ 2

Почему бы просто не использовать:

```{r, results='hide'}
DT[, c:=5]
```

Ответ 4

Просто окружайте выражение с помощью invisible(). Это работает для меня.

Ответ 5

Я столкнулся с одной и той же проблемой, и я решил ее довольно легко, переназначив переменную. В вашем случае:

DT <- DT[, ':=' (c, 5)]

Это немного более подробный, особенно, если имя переменной велико.