Понимание того, когда именно данные.таблица-это ссылка на (против копии) другие данные.стол
у меня возникли небольшие проблемы с пониманием свойств 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]