Подтвердить что ты не робот

Присвоить значение конкретным столбцам и строкам данных.

все еще понимая этот отличный пакет... Может ли кто-нибудь объяснить мне причину этой ошибки? Спасибо!

library(data.table)

DT <- data.table(id   = LETTERS,
                 var1 = rnorm(26),
                 var2 = rnorm(26))

> DT[2, list(var1, var2)]
            var1          var2
1: -0.8628479332 -0.2367492928
> DT[2, c(var1, var2)]
[1] -0.8628479332 -0.2367492928
> 
> DT[2, list(var1, var2)] <- DT[8, list(var1, var2)]
Error in `[<-.data.table`(`*tmp*`, 2, list(var1, var2), value = list(var1 = -0.394006912428776,  : 
  object 'var1' not found
> DT[2, c(var1, var2)] <- DT[8, c(var1, var2)]
Error in `[<-.data.table`(`*tmp*`, 2, c(var1, var2), value = c(-0.394006912428776,  : 
  object 'var1' not found
4b9b3361

Ответ 1

Во-первых, для эффективности рекомендуется использовать := вместо [<-. [<- в основном обеспечивается для обратной последовательности. Итак, я сначала проиллюстрирую, как эффективно использовать :=, чтобы получить то, что вам нужно. := - это присвоение по ссылке (и оно обновляет таблицу данных без копирования данных, поэтому очень быстро).

require(data.table)
DT <- data.table(x = 1:5, y = 6:10, z = 11:15)

Предположим, вы хотите изменить вторую строку "y" на вторую строку "y" :

DT[2, y := DT[5, y]] 

или эквивалентно

DT[2, `:=`(y = DT[5, y])]

Предположим, что вы хотите изменить вторую строку и "y" и "z" на соответствующую строку в строке 5, а затем:

DT[2, c("y", "z") := as.list(DT[5, c(y, z)])]

или эквивалентно

DT[2, `:=`(y = DT[5, y], z = DT[5, z])]

Теперь просто чтобы показать, как назначить с помощью [<- (хотя это явно не рекомендуется), это можно сделать следующим образом:

DT <- data.table(x = 1:5, y = 6:10, z = 11:15)
DT[1, c("y", "z")] <- as.list(DT[5, c(y, z)])

или эквивалентно, вы также можете передать номер столбца:

DT[1, 2:3] <- as.list(DT[5, c(y, z)])

Надеюсь, что это поможет.


Изменить 1

Как узнать, почему вы получили сообщение об ошибке:

Во-первых, RHS должен быть списком для [<-data.table, если ему назначено более 1 столбца.

Во-вторых, аргумент j слева от <- не оценивается в среде вашей таблицы данных. Таким образом, он должен знать, каковы значения для j. И так как вы предоставляете var1 и var2 ( без двойных кавычек, которые сделают их символьным вектором), это понимается как переменная. Таким образом, он проверяет переменные var1 и var2, но поскольку он не "видит" столбцы в вашей таблице данных .table как переменные (как обычно, когда вы выполняете присвоения и т.д. В RHS <-), он будет искать те же переменные в своей родительской среде, которая является глобальной средой, где она не находит их, и поэтому вы получаете ошибку. Например: сделайте следующее:

y <- "y"
z <- "z"
# And now try your second case: 
DT[2, c(y, z)] <- as.list(DT[5, c(y, z)])
# the left side takes values from the assignments you made above
# the right side y and z are evaluated within the environment of your data.table
# and so it sees the columns y and z as variables and their values are picked accordingly

В-третьих, функция [<-data.table допускает только atomic (векторный) тип для аргумента j. Итак, ваше первое назначение DT[2, list(var1, var2)] <- DT[8, list(var1, var2)] будет по-прежнему выдавать ошибку, если вы сделаете это правильно, то есть:

y <- "y"
z <- "z"
DT[2, list(y, z)] <- as.list(DT[5, c(y, z)])

# Error in `[<-.data.table`(`*tmp*`, 2, list(y, z), value = list(10L, 15L)) : 
#   j must be atomic vector, see ?is.atomic

надеюсь, что это поможет.


Изменить 2

Чтобы проиллюстрировать, что копия вашей таблицы данных выполняется, когда вы делаете [<-, но не тогда, когда :=,

DT <- data.table(x = 1:5, y = 6:10, z = 11:15)
tracemem(DT)
# [1] "<0x7fbefb89b580>"

DT[1, c("y", "z") := list(100L, 110L)]
tracemem(DT)
# [1] "<0x7fbefb89b580>"

DT[2, c("y", "z")] <- list(200L, 201L)
# tracemem[0x7fbefacc4fa0 -> 0x7fbefd297838]: # copied, inefficient