仍然了解这个伟大的包...有人可以解释一下这个错误的原因吗?谢谢!
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
答案 0 :(得分:35)
首先,建议使用:=
代替[<-
以提高效率。 [<-
主要是为了向后一致性而提供的。因此,我首先要说明如何有效地使用:=
来获取您所追求的内容。 :=
是按引用分配的(它会更新data.table而不复制数据,因此极快)。
require(data.table)
DT <- data.table(x = 1:5, y = 6:10, z = 11:15)
假设您要更改第二行&#34; y&#34;到第5行&#34; y&#34;:
DT[2, y := DT[5, y]]
或等效
DT[2, `:=`(y = DT[5, y])]
假设您要更改的第二行&#34; y&#34;和&#34; z&#34;到第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
的列表。
其次,j
左侧的<-
参数未在data.table的环境中进行评估。因此,它需要知道j
的值是什么。由于您提供var1
和var2
(没有双引号会使它们成为字符向量),因此它被理解为变量。因此,它检查变量var1
和var2
,但因为它没有&#34;&#34;&#34; data.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
希望这会有所帮助。
[<-
而不是:=
时,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