data.table 引入了 := 运算符。为什么不超载<-?
2 回答
有两个地方<-
可能会“超载”:
x[i, j] <- value # 1
x[i, {colname <- value}] # 2
第一个复制整个x
to *tmp*
,更改该工作副本,然后分配回x
。这是最近在 r-devel 上讨论的 R 事物(src/main/eval.c 和 subassign.c )。听起来可能可以更改 R 以允许包或 R 本身,以避免复制到*tmp*
IIUC,但目前不可能。
我认为第二个是欧文的回答所指的。如果您接受可以像这样通过引用进行赋值j
,那么哪个运算符?根据对欧文回答的评论,<-
并且<<-
已经被用户使用j
,所以我们找到了:=
。
即使[<-
没有复制整个x
,我们仍然喜欢:=
inj
所以我们可以这样做:
DT[,{newcol1:=sum(a)
newcol2:=a/newcol1}, by=group]
其中新列是通过引用表添加的,并且每个组的 RHS 都:=
在每个组内进行评估。(当 := 组内实施时。)
2012 年 10 月更新
从 1.8.2 开始(2012 年 7 月在 CRAN 上),实现了:=
按组添加或更新单个列;即, 的单个 LHS :=
。现在在 v1.8.3 中(撰写本文时在 R-Forge 上),可以按组添加多个列;例如,
DT[, c("newcol1","newcol2") := .(sum(a),sum(b)), by=group]
或者,也许更优雅:
DT[,`:=`(newcol1=sum(a),
newcol2=sum(b)), by=group]
但是,设想了一段时间的迭代多个 RHS,其中第二个表达式可以使用第一个表达式的结果,尚未实现 ( FR#1492 )。所以这仍然会出错"newcol1 not found"
,需要分两步完成:
DT[,`:=`(newcol1=sum(a),
newcol2=a/newcol1), by=group]
我认为这没有任何技术原因是必要的,原因如下::=
仅在内部使用,[...]
因此始终被引用。[...]
遍历表达式树以查看是否:=
在其中。
这意味着它并没有真正充当运算符,也没有真正过载;所以他们几乎可以选择任何他们想要的操作员。我想也许它看起来更好?或者不那么令人困惑,因为它显然不是<-
?
(请注意,如果:=
在它之外使用,[...]
则不能是<-
,因为您实际上不能重载<-
。<-
不评估其左侧参数,因此它不知道类型是什么)。