在data.frames元素的列表中使用data.table函数(Answer = setDT)

时间:2017-02-07 17:50:46

标签: r data.table lapply

第一个问题,如果评论中需要更多信息或背景,请告诉我。

这里和其他地方的许多答案都涉及在data.table函数中调用lapply。我想做相反的事情,在纸面上应该很容易lapply(list.of.dfs, fun(x) x)但是我无法使用data.table函数。

我有一个列表,其中包含几个具有相同列但行数不同的data.frames。这来自几个模拟场景的输出,因此必须单独处理它们而不是rbind&#39。

 #sample list of data.frames
  scenarios <- replicate(5, data.frame(a=sample(letters[1:4],10,T),
                              b=sample(1:2,10,T),
                              x=sample(1:10, 10), 
                              y =runif(10)), simplify = FALSE)

我想为每个元素添加一个列,即a和b的x / y之和。
从示例部分的data.table文档中,对一个data.frame执行此操作的过程如下(搜索:在doc页面中按组引用添加新列):

test <- as.data.table(scenarios[[1]]) #must specify data.table class
test[, newcol := sum(x/y), by = .(a , b)][]

我想使用lapply对方案列表中的每个元素执行相同的操作并返回列表。 我最近的尝试:

lapply(scenarios, function(i) {as.data.table(i[, z := sum(x/y), by=.(a,b)]); i})

但我一直收到错误unused argument (by = .a,b))

在倾倒了这个和其他网站的结果后,我一直无法解决这个问题。我非常确定这意味着我有一些关于调用匿名函数和/或使用data.table函数的东西。这是一个你使用[作为功能?或者我的as.data.table可能不合适。

This answer是朝着正确方向迈出的一步(我认为),它涵盖了fun(x)的使用{...; x}使用匿名函数并返回x。

谢谢!

1 个答案:

答案 0 :(得分:2)

您可以在此处使用setDT

scenarios <- lapply(scenarios, function(i) setDT(i)[, z := sum(x/y), by=.(a,b)])

scenarios[[1]]
   a b  x          y         z
 1: c 2  2 0.87002174  2.298793
 2: b 2 10 0.19720775 78.611837
 3: b 2  8 0.47041670 78.611837
 4: b 2  4 0.36705023 78.611837
 5: a 1  5 0.78922686 12.774035
 6: a 1  6 0.93186209 12.774035
 7: b 1  3 0.83118438  3.609307
 8: c 1  1 0.08248658 30.047494
 9: c 1  7 0.89382050 30.047494
10: c 1  9 0.89172831 30.047494

使用as.data.table,语法为

scenarios <- lapply(scenarios, function(i) {i <- as.data.table(i); i[, z := sum(x/y),
                                                                     by=.(a,b)]})

但不建议这样做,因为它会创建一个额外的副本,setDT可以避免这种情况。