在R中,data.table的:=表达式语法是什么?

4

我在使用R中的data.table时遇到了一些麻烦,无法对表达式进行求值。下面是一些代码:

dtb = data.table(a=1:100, b=100:1, id=1:10)
dtb[,`:=`(c=a+b, d=a/b),by=id] #this works fine
expr = expression({`:=`(c=a+b, d=a/b)}) #try to couch everything in an expression
dtb[,eval(expr),by=id] #this does not work
Error in `:=`(c = a + b, d = a/b) : 
   unused argument(s) (c = a + b, d = a/b)

expr = expression(`:=`(c=a+b, d=a/b)) #this works fine
dtb[,eval(expr),by=id] 

为什么包含{}会使它出错?

如果eval()是答案,那么你几乎肯定问错了问题。 - Matthew Lundberg
1
@MatthewLundberg:哈哈,谢谢。实际上,在data.table中使用eval是正确的方法:) - Alex
你真正想问的是为什么 dtb[,{\:=`(c=a+b, d=a/b)},by=id]` 不能工作,对吗? - GSee
@GSee:是的,我相信它们是等价的,但我只是想在这里放置我所拥有的确切语法。 - Alex
2
@Alex,你使用了一些不恰当的措辞“不起作用”。试着考虑一下如果你没有提供错误信息或展示预期结果与实际结果的区别,回答起来会有多难。我经常使用手机阅读和回答问题。即使我手头有R会话,我也会感到恼怒,因为你本可以更方便地提供信息,而我却要额外付出复制和粘贴的努力。即使如此,我可能还会看到不同的错误答案,这只会浪费时间。 - Matt Dowle
@MatthewDowle:好的,如果这有帮助的话,让我加上错误信息。 - Alex
2个回答

7

查看:=的定义:

function (LHS, RHS) 
stop(":= is defined for use in j only, and (currently) only once; i.e., DT[i,col:=1L] and DT[,newcol:=sum(colB),by=colA] are ok, but not DT[i,col]:=1L, not DT[i]$col:=1L and not DT[,{newcol1:=1L;newcol2:=2L}]. Please see help(\":=\"). Check is.data.table(DT) is TRUE.")

一个列的赋值不会在调用:=时发生——函数本身除了产生一个错误之外什么也不做。当[.data.table检测到j是一个形式为`:=`(...)的表达式时,赋值才会发生,并设置好调用C代码的所有内容。当你将expr括在方括号中时,你正在将表达式的第一部分变成{而不是:=,这样就可以绕过上述检测,最终结果是使用参数cd:=进行评估。
我想这会引出一个问题,为什么需要将其括在{ }中?

有趣 - 让 Dowle 确认一下 - Alex
我刚意识到你的问题是针对我的:最初将它括在 {} 中的原因是因为每当我使用 data.table 并且有一堆表达式时,习惯性地将它们括起来,因为有多个语句。但在这种情况下只有一个语句,所以没有必要这样做。 - Alex
1
通过这些错误消息和用户57的解释,是的,所有都符合。改进将是使用“...”定义':='并改进错误消息。您可以在':='(...)的RHS上使用{},并在每个RHS上使用{}。这是因为dogroups.c要么通过引用更新,要么返回一个新的data.table,而不是两者混合。 - Matt Dowle

5

问题 #376 已在 v1.8.11 中实现,用于捕获 {:= 之间的内容。从新闻中了解到:

o 现在已经实现了 FR #2496,用于捕获并删除 j:= 周围的 {,以获得所需的结果。现在,DT[,{`:=`(...)}]DT[, {`:=`(...)}, by=(...)] 都能按预期工作,但会发出警告。感谢 Alex 在 SO 上的报告:R 中 data.table := 的表达式语法


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接