Почему имена обновления data.table (DT) по ссылке, даже если я назначаю другую переменную?

Я сохранил имена data.table в виде vector :

 library(data.table) set.seed(42) DT <- data.table(x = runif(100), y = runif(100)) names1 <- names(DT) 

Насколько я могу судить, это простой вектор символа ванили:

 str(names1) # chr [1:2] "x" "y" class(names1) # [1] "character" dput(names1) # c("x", "y") 

Однако это не обычный вектор символов. Это волшебный вектор символов! Когда я добавляю новый столбец в мою data.table Этот вектор обновляется!

 DT[ , z := runif(100)] names1 # [1] "x" "y" "z" 

Я знаю, что это имеет какое-то отношение к тому, как := обновления по назначению, но это все еще кажется мне волшебным, так как я ожидаю, что <- data.table копию data.table .

Я могу исправить это, обернув имена в c() :

 library(data.table) set.seed(42) DT <- data.table(x = runif(100), y = runif(100)) names1 <- names(DT) names2 <- c(names(DT)) all.equal(names1, names2) # [1] TRUE DT[ , z := runif(100)] names1 # [1] "x" "y" "z" names2 # [1] "x" "y" 

Мой вопрос в 2 раза:

  1. Почему names1 <- names(DT) создают копию data.table ? В других случаях мы явно предупреждаем, что <- создает копии, как data.table s, так и data.frame s.
  2. В чем разница между names1 <- names(DT) и names2 <- c(names(DT)) ?

Обновление: теперь это добавлено в документацию для ?copy в версии 1.9.3. Из новостей :

  1. Перемещено ?copy на свою страницу справки и задокументируйте, что dt_names <- copy(names(DT)) необходимо, чтобы dt_names не были изменены ссылкой в ​​результате обновления DT по ссылке (например: добавление нового столбца по ссылке) , Закрывает # 512 . Спасибо Заху за этот вопрос и пользователь1971988 за этот вопрос .

Часть вашего первого вопроса немного меня нечетко говорит о том, что вы действительно имеете в виду о <- operator (по крайней мере, в контексте data.table ), особенно в части: В других случаях мы явно предупреждаем, что <- создает копии, как data.tables, так и data.frames.

Поэтому, прежде чем ответить на ваш реальный вопрос, я кратко коснусь его здесь. В случае data.table a <- (присваивание) просто недостаточно для копирования data.table . Например:

 DT <- data.table(x = 1:5, y= 6:10) # assign DT2 to DT DT2 <- DT # assign by reference, no copy taken. DT2[, z := 11:15] # DT will also have the z column 

Если вы хотите создать copy , вы должны явно указать ее с помощью команды copy .

 DT2 <- copy(DT) # copied content to DT2 DT2[, z := 11:15] # only DT2 is affected 

Из CauchyDistributedRV я понимаю, что вы имеете в виду names(dt) <- . присваивания names(dt) <- . что приведет к предупреждению. Я оставлю это как таковое.


Теперь, чтобы ответить на ваш первый вопрос: Кажется, что names1 <- names(DT) также ведут себя аналогичным образом. Я до сих пор не думал об этом. Команда .Internal(inspect(.)) Очень полезна здесь:

 .Internal(inspect(names1)) # @7fc86a851480 16 STRSXP g0c7 [MARK,NAM(2)] (len=2, tl=100) # @7fc86a069f68 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "x" # @7fc86a0f96d8 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "y" .Internal(inspect(names(DT))) # @7fc86a851480 16 STRSXP g0c7 [MARK,NAM(2)] (len=2, tl=100) # @7fc86a069f68 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "x" # @7fc86a0f96d8 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "y" 

Здесь вы видите, что они указывают на то же расположение памяти @7fc86a851480 . Даже truelength прав на names1 равна 100 (что по умолчанию выделено в data.table , для этого data.table проверить ?alloc.col ).

 truelength(names1) # [1] 100 

Таким образом, names1 <- names(dt) присваивания1 names1 <- names(dt) видимому, происходят по ссылке. То есть names1 указывают на то же место, что и указатель имен столбцов dt.

Чтобы ответить на ваш второй вопрос: команда c(.) Похоже, создает копию, поскольку нет проверки того, что результат содержимого из-за операции конкатенации различен . То есть, поскольку операция c(.) Может изменять содержимое вектора, это немедленно приводит к тому, что выполняется «копия», не проверяя, не изменяется ли содержимое.

  • Количество столбцов по условию (>) для каждой строки
  • В чем разница между `=` и `<-` в R?
  • Строка ggplot2 дает «geom_path: каждая группа состоит только из одного наблюдения. Вам нужно настроить группу эстетики? "
  • Как отображать только целые значения на оси с помощью ggplot2
  • Приведение полиномиальной модели к данным в R
  • Планирование R Script
  • Удаление определенных строк из фрейма данных
  • Как рисовать с помощью png в качестве фона?
  • Зацикливание объекта datetime приводит к числовому iteratorу
  • Как читать параметры командной строки из R-скрипта?
  • Подобная функция репрезентации R в Matlab
  • Давайте будем гением компьютера.