在一个函数调用中向R data.table添加多个列?

Flo*_*ald 67 r data.table

我有一个函数,在列表中返回两个值.这两个值都需要添加到两个新列的data.table中.对功能的评估是昂贵的,所以我想避免必须两次计算功能.这是一个例子:

library(data.table)
example(data.table)
DT
   x y  v
1: a 1 42
2: a 3 42
3: a 6 42
4: b 1  4
5: b 3  5
6: b 6  6
7: c 1  7
8: c 3  8
9: c 6  9
Run Code Online (Sandbox Code Playgroud)

这是我的功能的一个例子.记住我说这是昂贵的计算,除此之外,没有办法从其他给定值中推导出一个返回值(如下例所示):

myfun <- function (y, v) 
{
ret1 = y + v
ret2 = y - v
return(list(r1 = ret1, r2 = ret2))
}
Run Code Online (Sandbox Code Playgroud)

这是我在一个语句中添加两列的方法.那个人需要两次打电话给myfun:

DT[,new1:=myfun(y,v)$r1][,new2:=myfun(y,v)$r2]

   x y  v new1 new2
1: a 1 42   43  -41
2: a 3 42   45  -39
3: a 6 42   48  -36
4: b 1  4    5   -3
5: b 3  5    8   -2
6: b 6  6   12    0
7: c 1  7    8   -6
8: c 3  8   11   -5
9: c 6  9   15   -3
Run Code Online (Sandbox Code Playgroud)

有关如何做到这一点的任何建议?r2每次调用myfun时,我都可以保存在一个单独的环境中,我只需要一种方法一次通过引用添加两列.

flo*_*del 91

您可以存储函数调用的输出:

DT[, c("new1","new2") := myfun(y,v)]
Run Code Online (Sandbox Code Playgroud)

但这似乎也有效:

z <- myfun(DT$y,DT$v)
head(DT[,new1:=z$r1][,new2:=z$r2])
#      x y  v new1 new2
# [1,] a 1 42   43  -41
# [2,] a 3 42   45  -39
# [3,] a 6 42   48  -36
# [4,] b 1  4    5   -3
# [5,] b 3  5    8   -2
# [6,] b 6  6   12    0
Run Code Online (Sandbox Code Playgroud)

为了方便起见data.table,在R-Forge的v1.8.3中新增了,data.table这里不再需要了:

DT[, c("new1","new2") := myfun(y,v)]
Run Code Online (Sandbox Code Playgroud)

最新的现场新闻在这里.

  • 请注意,列表回收也已完成; 例如,`c("a","b","c","d"):= list(1,2)`将1放入`a`和`c`,将2放入`b`和`d `.如果任何列不存在,则将通过引用添加.不确定`:=`回收在实践中是多么有用.它更适用于`c("a","b","c"):= NULL`删除这3列.在内部,这是一个NULL回收到(语义)列表长度3. (7认同)
  • 另一个有用的`:=`用法可以是`\`:= \`(colname = colvalue,...)`.我经常喜欢这个,因为你可能只用`list`替换`:=`来使用`:=`时通过引用写入数据的只读预览. (7认同)
  • 哇,第二个是惊人的,谢谢!只需用`debug(myfun)`来运行它,看看它被调用的次数:它只是一次.大. (2认同)