data.table:lapply一个具有多列输出的函数

mat*_*tek 5 r hmisc data.table

我正在使用smean.cl.normalHmisc包中的一个函数,该函数返回一个包含3个值的向量:均值和低位和高位CI.当我在data.table2组使用它时,我获得2列和6行.有没有办法获得结果,两行对应2组,每个函数的输出分别列,即均值和CI?

require(Hmisc)
require(data.table)

dt = data.table(x = rnorm(100),
                gr = rep(c('A', 'B'), each = 50))

dt[, lapply(.SD, smean.cl.normal), by = gr, .SDcols = "x"]
Run Code Online (Sandbox Code Playgroud)

输出:

   gr           x
1:  A -0.07916335
2:  A -0.33656667
3:  A  0.17823998
4:  B -0.02745333
5:  B -0.32950607
6:  B  0.27459941
Run Code Online (Sandbox Code Playgroud)

所需的输出:

   gr        Mean         Lower         Upper
1:  A -0.07916335   -0.33656667    0.17823998
2:  B -0.02745333   -0.32950607    0.27459941
Run Code Online (Sandbox Code Playgroud)

Fra*_*ank 8

期望列表中的j参数DT[i,j,by],所以使用as.list:

dt[, 
  Reduce(c, lapply(.SD, function(x) as.list(smean.cl.normal(x))))
, by = gr, .SDcols = "x"]

#    gr       Mean      Lower     Upper
# 1:  A  0.1032966 -0.1899466 0.3965398
# 2:  B -0.1437617 -0.4261330 0.1386096
Run Code Online (Sandbox Code Playgroud)

c(L1, L2, L3)是如何组合列表,所以Reduce(c, List_o_Lists)如果你.SDcols包含的不仅仅是诀窍x.我想do.call(c, List_o_Lists)也应该有用.


评论

由于几个原因,这是非常低效的.打开verbose=TRUE以查看data.table不喜欢在j以下位置获取命名列表:

j的结果是一个命名列表.为每个组反复创建相同的名称效率非常低.当j = list(...)时,为了提高效率,在分组完成后检测,删除和放回任何名称.例如,使用j = transform()可以防止加速(考虑更改为:=).此消息可能会在将来升级为警告.

此外,您错过了mean可能用于构建结果的组优化版本和其他功能.不过,这对你的用例来说可能不是什么大问题.


当您将其应用于单个值列时,只需:

dt[, as.list(smean.cl.normal(x)), by = gr]
Run Code Online (Sandbox Code Playgroud)

就足够了.