data.table引入了:=运算符。为什么不超载<-?
<-
可能在两个地方"过载":
x[i, j] <- value # 1
x[i, {colname <- value}] # 2
第一个将整个x
复制到*tmp*
,更改该工作副本,并分配回x
。这是最近在R-devel上讨论的R(src/main/eval.c和subassign.c(。听起来可能可以更改R以允许包,或者更改R本身以避免复制到*tmp*
,但目前不可能,IIUC。
第二个问题是欧文的回答,我认为。如果你接受这样在j
中通过引用进行赋值是可以的,那么是哪个操作符?根据对Owen回答的评论,<-
和<<-
已经被j
中的用户使用,所以我们偶然发现了:=
。
即使[<-
没有复制整个x
,我们仍然喜欢j
中的:=
,所以我们可以这样做:
DT[,{newcol1:=sum(a)
newcol2:=a/newcol1}, by=group]
其中,通过引用表添加新列,并在每组中评估每个:=
的RHS。(当:=在组内执行时。(
2012年10月更新
截至1.8.2(2012年7月在CRAN上(,组实现了:=
,用于添加或更新单列;即CCD_ 17的单个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]
我认为没有任何技术原因需要这样做,原因如下::=
只在[...]
中使用,所以它总是被引用。[...]
遍历表达式树以查看:=
是否在其中
这意味着它并没有真正充当运营商,也没有真正超载;所以他们几乎可以选择任何他们想要的运营商。我想也许它看起来更好?或者因为它显然不是<-
而不那么令人困惑?
(请注意,如果:=
在[...]
的外部使用,则它不可能是<-
,因为实际上无法重载<-
。<-
不计算其左手参数,因此它不知道类型是什么(。