Понимание того, когда именно данные.таблица-это ссылка на (против копии) другие данные.стол
у меня возникли небольшие проблемы с пониманием свойств pass-by-reference data.table
. Некоторые операции, похоже, "ломают" ссылку, и я хотел бы точно понять, что происходит.
о создании data.table
С другой data.table
(через <-
, затем обновление новой таблицы с помощью :=
, оригинальная таблица также изменяется. Это ожидается, согласно:
?data.table::copy
и stackoverflow: передача по ссылке-оператор--в--данные-таблицы-пакет
вот пример:
library(data.table)
DT <- data.table(a=c(1,2), b=c(11,12))
print(DT)
# a b
# [1,] 1 11
# [2,] 2 12
newDT <- DT # reference, not copy
newDT[1, a := 100] # modify new DT
print(DT) # DT is modified too.
# a b
# [1,] 100 11
# [2,] 2 12
однако, если я вставляю не:=
модификации между <-
назначение и конструкция :=
выше линии, DT
теперь больше не изменяется:
DT = data.table(a=c(1,2), b=c(11,12))
newDT <- DT
newDT$b[2] <- 200 # new operation
newDT[1, a := 100]
print(DT)
# a b
# [1,] 1 11
# [2,] 2 12
так кажется, что newDT$b[2] <- 200
строка как-то "ломает" ссылки. Я бы предположил, что это каким-то образом вызывает копию, но я хотел бы полностью понять, как R обрабатывает эти операции, чтобы убедитесь, что я не ввожу потенциальные ошибки в моем коде.
Я был бы очень признателен, если бы кто-нибудь объяснил мне это.
2 ответа:
просто краткое резюме.
<-
Сdata.table
точно так же, как base; т. е. никакая копия не берется до тех пор, пока подзадача не будет выполнена впоследствии с<-
(например, изменение имен столбцов или изменение элемента, напримерDT[i,j]<-v
). Затем он берет копию всего объекта так же, как база. Это известно как копирование на запись. Было бы лучше известно как копия-на-субассин, я думаю! Он не копируется при использовании специального:=
оператора, илиset*
функции, предусмотренныеdata.table
. Если у вас есть большие данные, которые вы, вероятно, хотите использовать их.:=
иset*
не будет копироватьdata.table
, ДАЖЕ В ПРЕДЕЛАХ ФУНКЦИЙ.учитывая этот пример данных:
DT <- data.table(a=c(1,2), b=c(11,12))
следующее просто "связывает" другое имя
DT2
к тому же объекту данных привязан в настоящее время привязан к имениDT
:DT2 <- DT
это никогда не копирует, и никогда не копирует в базу либо. Он просто помечает объект данных, чтобы R знал, что два разных имени (
DT2
иDT
) указывают на тот же объект. И поэтому R нужно будет скопировать объект, Если либо subassigned потом.это идеально подходит для
data.table
тоже. Элемент:=
не для этого. Таким образом, следующее является преднамеренной ошибкой как:=
не только для привязки имен объекта :DT2 := DT # not what := is for, not defined, gives a nice error
:=
на subassigning по ссылке. Но вы не используете его, как вы бы в базе :DT[3,"foo"] := newvalue # not like this
вы используйте его так:
DT[3,foo:=newvalue] # like this
что изменилось
DT
по ссылке. Скажем, вы добавляете новый столбецnew
со ссылкой на объект данных, нет необходимости делать это :DT <- DT[,new:=1L]
потому что RHS уже изменился
DT
по ссылке. ДополнительныеDT <-
- это значит не понимать, что:=
делает. Вы можете написать его там, но это лишнее.
DT
изменяется по ссылке, по:=
, ДАЖЕ В ПРЕДЕЛАХ ФУНКЦИЙ :f <- function(X){ X[,new2:=2L] return("something else") } f(DT) # will change DT DT2 <- DT f(DT) # will change both DT and DT2 (they're the same data object)
data.table
для больших наборов данных, помните. Если у вас есть 20GBdata.table
в памяти, то вам нужен способ, чтобы сделать это. Это очень продуманное дизайнерское решениеdata.table
.копии могут быть сделаны, конечно. Вам просто нужно рассказать данные.таблица, в которой вы уверены, что хотите скопировать свой набор данных 20GB, используя
copy()
функция :DT3 <- copy(DT) # rather than DT3 <- DT DT3[,new3:=3L] # now, this just changes DT3 because it's a copy, not DT too.
чтобы избежать копирования, не используйте назначение базового типа или обновление:
DT$new4 <- 1L # will make a copy so use := attr(DT,"sorted") <- "a" # will make a copy use setattr()
если вы хотите быть уверены, что вы обновляете по ссылке использовать
.Internal(inspect(x))
и посмотрите на значения адресов памяти составляющих (см. ответ Мэтью Доула).писать
:=
наj
как это позволяет вам назначить по ссылке группы. Вы можете добавить новый столбец по ссылке по группам. Так вот почему:=
делается таким образом внутри[...]
:DT[, newcol:=mean(x), by=group]