Почему имена обновления 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
Этот вектор обновляется!
- Кривая кривой полинома в R
- Поместите звезды на ggplot barplots и boxplots - чтобы указать уровень значимости (p-value)
- измените оба названия легенды в ggplot с двумя легендами
- Как работать с большими числами в R?
- Как определить правильную кодировку для read.csv?
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 раза:
- Почему
names1 <- names(DT)
создают копиюdata.table
? В других случаях мы явно предупреждаем, что<-
создает копии, какdata.table
s, так иdata.frame
s. - В чем разница между
names1 <- names(DT)
иnames2 <- c(names(DT))
?
- Что такое семантика copy-on-modify в R, а где канонический источник?
- фильтр для полных случаев в data.frame с использованием dplyr (случайное удаление)
- Преобразование матрицы в одномерный массив
- Найдите дополнение к кадру данных (антисоединение)
- Как `poly ()` генерирует ортогональные полиномы? Как понять, что «коэф.» Вернулись?
- Суммируя несколько столбцов с dplyr?
- Подмножество data.table с использованием переменных с тем же именем, что и в столбце
- Как использовать data.table внутри функций и циклов?
Обновление: теперь это добавлено в документацию для ?copy
в версии 1.9.3. Из новостей :
- Перемещено
?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(.)
Может изменять содержимое вектора, это немедленно приводит к тому, что выполняется «копия», не проверяя, не изменяется ли содержимое.