为什么要定义data.table:=而不是重载< – ?
data.table引入了:=运算符。 为什么不过载< – ?
我不认为这是有必要的,因为以下原因:=
只用于内部,所以它总是引用。 [...]
遍历expression式树来查看是否存在:=
。
这意味着它不是真的作为一个操作符,它不是真的超载; 所以他们可以挑选他们想要的任何运营商。 我想也许它看起来更好? 或者更less混乱,因为它显然不是<-
?
(请注意,如果:=
在[...]
之外使用,则不能<-
,因为实际上不能重载<-
。 <-
不计算其左手参数,因此它不知道types是)。
有两个地方可能会被“超载”:
x[i, j] <- value # 1 x[i, {colname <- value}] # 2
第一个将整个x
复制到*tmp*
,更改该工作副本,并将其分配回x
。 这是一个R的东西(src / main / eval.c和subassign.c)最近在r-devel 这里讨论过。 听起来好像有可能把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)开始,按:=
组进行添加或更新单列; 即单个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]
但是,第二个expression式可以使用第一个expression式的迭代多重RHS尚未实现( FR#1492 )。 所以这仍然会给出一个错误"newcol1 not found"
,需要分两步完成:
DT[,`:=`(newcol1=sum(a), newcol2=a/newcol1), by=group]