为什么定义了data.table:=而不是重载< - ?

Mat*_*wle 44 r data.table colon-equals

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

Mat*_*wle 29

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

x[i, j] <- value           # 1
x[i, {colname <- value}]   # 2
Run Code Online (Sandbox Code Playgroud)

第一个拷贝整个的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]
Run Code Online (Sandbox Code Playgroud)

通过引用表添加新列的位置,并:=在每个组中评估每个列的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]
Run Code Online (Sandbox Code Playgroud)

或者,也许更优雅:

DT[,`:=`(newcol1=sum(a),
         newcol2=sum(b)), by=group]
Run Code Online (Sandbox Code Playgroud)

但设想一段时间的迭代多重RHS,其中第二个表达式可以使用第一个表达式的结果,尚未实现(FR#1492).所以这仍然会出错"newcol1 not found",需要分两步完成:

DT[,`:=`(newcol1=sum(a),
         newcol2=a/newcol1), by=group]
Run Code Online (Sandbox Code Playgroud)

  • 只是一个小问题,`x [i,j] < - value`实际上并没有重载`<-`,而是`<-`通过委托给`[< - `来做它总是做的事情(基于表达式,不是价值类型). (3认同)

Owe*_*wen 16

我不认为有任何技术原因这是必要的,原因如下::=只在内部使用,[...]所以总是引用它.[...]通过表达式树来查看是否:=在其中.

这意味着它并没有真正作为一个运营商,它并没有真正超载; 所以他们可以选择他们想要的任何操作员.我想也许它看起来更好?或者更少混淆,因为它显然不是<-

(注意,如果:=在它之外使用[...]它是不可能的<-,因为你实际上不能超载<-.<-不评估它的左手参数,因此它不知道类型是什么).

  • 是的,这就是它.我们尝试< - 首先实际但是因为用户代码已经使用了< - 例如递增组计数器而没有飞行.然后我们尝试了<< - 但人们已经在j中使用它,分配给.GlobalEnv.那么我们就来了:=. (7认同)