首先,建议使用:=
代替[<-
为了效率。这[<-
主要是为了向后一致性而提供的。因此,我将首先说明如何有效地使用:=
得到你想要的东西。:=
是通过引用分配(并且它更新 data.table 而不复制数据,因此极其 fast).
require(data.table)
DT <- data.table(x = 1:5, y = 6:10, z = 11:15)
假设您要将“y”的第 2 行更改为“y”的第 5 行:
DT[2, y := DT[5, y]]
或同等地
DT[2, `:=`(y = DT[5, y])]
假设你想改变第二行both将“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)])
希望这可以帮助。
Edit 1
至于为什么会出现错误:
首先,RHS 必须是一个列表[<-data.table
如果要分配的列超过 1 列。
Second, j
左边的参数<-
不在您的 data.table 环境中进行评估。所以,它需要知道什么是值j
是。既然你提供了var1
and var2
(没有双引号这将使它们成为字符向量),它被理解为一个变量。因此,它检查变量var1
and var2
,但因为它不会将 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
希望这可以帮助。
Edit 2
只是为了说明当您这样做时正在制作 data.table 的副本[<-
但不是当:=
,
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