Использование setDT внутри функции
Я пишу функцию, которая, между прочим, принуждает ввод к таблице данных.
library(data.table)
df <- data.frame(id = 1:10)
f <- function(df){setDT(df)}
f(df)
df[, temp := 1]
Однако последняя команда выводит следующее предупреждение:
Предупреждающее сообщение: В [.data.table
(df, :=
(temp, 1)): Недействительный .Internal.selfref обнаружены и исправлены, взяв копию целого таблицу, чтобы: = добавить новый столбец по ссылке. При более раннем point, эта таблица данных была скопирована R (или была создана вручную используя структуру() или аналогичную). Избегайте ключевых < -, имен < - и attr < - которые в R в настоящее время (и странно) может скопировать всю таблицу данных. Используйте set * вместо этого следует избегать копирования:? set,? setnames и? setattr. Также, в R <= v3.0.2, список (DT1, DT2) скопировал весь DT1 и DT2 (список R() используется для копирования названных объектов); обновите до R > v3.0.2, если это кусаться. Если это сообщение не помогает, сообщите в службу данных поэтому основная причина может быть исправлена.
Я использую v1.9.3 data.table и R 3.1.1. Означает ли это, что df
копируется в какой-то момент? Как избежать этого предупреждения?
Изменить:
Код setDT
фактически использует NSE. Таким образом, это работает:
df1 <- data.frame(id = 1:10)
f <- function(df){eval(substitute(setDT(df)),parent.frame())}
f(df1)
df1[, temp := 1]
Кажется, я могу делать другие вещи с df внутри функции f
, например
df1 <- data.frame(id = 1:10)
f <- function(df){
eval(substitute(setDT(df)),parent.frame())
df[, temp := 1]
}
f(df1)
Правильно ли это сделать?
Ответы
Ответ 1
Отличный вопрос! Предупреждающее сообщение должно указывать:... и фиксироваться с помощью неглубокой копии всей таблицы... Будет исправлено это.
setDT
выполняет две вещи:
- установите класс
data.table
из data.frame
/list
- используйте
alloc.col
для перераспределения столбцов (так что :=
можно использовать напрямую)
И для второго шага требуется неглубокая копия, если вход уже не является data.table
. И именно поэтому мы присваиваем значение обратно символу в этой среде (родительский кадр setDT). Но родительский кадр для setDT
является вашей функцией f()
. Поэтому setDT(df)
внутри вашей функции прошел гладко, но df
, который находится в глобальной среде, изменит класс, а не перераспределение (поскольку мелкая копия разорвала ссылку).
И на следующем шаге :=
обнаруживает, что и мелкие копии еще раз перераспределяют.
Идея заключается в том, чтобы использовать setDT
для преобразования в data.tables перед тем, как предоставить ее функции. Но я хотел бы, чтобы эти случаи были разрешены (посмотрим).
Спасибо, куча!