49

data.table 引入了 := 运算符。为什么不超载<-?

4

2 回答 2

31

有两个地方<-可能会“超载”:

x[i, j] <- value           # 1
x[i, {colname <- value}]   # 2

第一个复制整个xto *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]
于 2011-08-11T23:42:01.037 回答
18

我认为这没有任何技术原因是必要的,原因如下::=仅在内部使用,[...]因此始终被引用。[...]遍历表达式树以查看是否:=在其中。

这意味着它并没有真正充当运算符,也没有真正过载;所以他们几乎可以选择任何他们想要的操作员。我想也许它看起来更好?或者不那么令人困惑,因为它显然不是<-

(请注意,如果:=在它之外使用,[...]则不能是<-,因为您实际上不能重载<-<-不评估其左侧参数,因此它不知道类型是什么)。

于 2011-08-11T22:11:14.163 回答