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

时间:2017-02-10 16:03:42

标签: r data.table hmisc

我正在使用来自Hmisc包的函数import index from '../src/components/index.vue'; import home from '../src/components/home.vue'; import NotFoundView from '../src/components/notfound.vue'; const routes = [ { path: '/login', component: index}, { path: '/', component: home}, { path: '*', component: NotFoundView } ] export default routes,该函数返回一个具有3个值的向量:均值和低位和高位CI。当我在具有2组的smean.cl.normal上使用它时,我获得2列和6行。有没有办法获得结果,其中两行对应于2个组,每个函数的输出都有不同的列,即均值和CI?

data.table

输出:

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"]

所需的输出:

   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

1 个答案:

答案 0 :(得分:6)

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

c(L1, L2, L3)是如何合并列表的,因此如果Reduce(c, List_o_Lists)包含的不仅仅是.SDcolsx就可以解决问题。我猜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]

就足够了。