8

我正在寻找用于操作data.table其结构类似于meltreshape2包中创建的数据框的对象的模式。我正在处理具有数百万行的数据表。性能至关重要。

问题的一般形式是是否有一种方法可以根据列中的值子集执行分组,并让分组操作的结果创建一个或多个新列。

问题的一种特定形式可能是如何使用data.table来完成dcast以下内容的等效操作:

input <- data.table(
  id=c(1, 1, 1, 2, 2, 2, 3, 3, 3, 3), 
  variable=c('x', 'y', 'y', 'x', 'y', 'y', 'x', 'x', 'y', 'other'),
  value=c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
dcast(input, 
  id ~ variable, sum, 
  subset=.(variable %in% c('x', 'y')))

其输出是

  id  x  y
1  1  1  5
2  2  4 11
3  3 15  9
4

3 回答 3

9

未经测试的快速答案:似乎您正在寻找by-without-by,也就是grouping-by-i

setkey(input,variable)
input[c("x","y"),sum(value)]

这就像 SQL 中的快速 HAVING。j对 的每一行进行评估i。换句话说,上面是相同的结果,但比:

input[,sum(value),keyby=variable][c("x","y")]

在仅选择感兴趣的组之前,对所有组(浪费地)进行后一个子集和评估。前者(by-without-by)仅直接进入组的子集。

与往常一样,组结果将以长格式返回。但是之后在(相对较小的)聚合数据上重新调整到广泛的范围应该是相对即时的。反正就是这么想的。

如果有很多不感兴趣的列,第一个setkey(input,variable)可能会咬人。input如果是这样,可能值得对所需的列进行子集:

DT = setkey(input[ , c("variable","value")], variable)
DT[c("x","y"),sum(value)]

将来实现辅助键时会更容易:

set2key(input,variable)              # add a secondary key 
input[c("x","y"),sum(value),key=2]   # syntax speculative

也可以分组id

setkey(input,variable)
input[c("x","y"),sum(value),by='variable,id']

根据您的数据,包括id在密钥中可能是值得的成本:setkey

setkey(input,variable,id)
input[c("x","y"),sum(value),by='variable,id']

如果您将 by-without-by 与 by 组合在一起,如上所述,那么 by-without-by 就像子集一样运行;即,j仅在i缺少 by 时为每一行运行(因此名称为by-without-by)。因此,您需要variable再次包含 ,by如上所示。

或者,以下内容应通过id“x”和“y”的并集进行分组(但以上是您在问题中所要求的,iiuc):

input[c("x","y"),sum(value),by=id]
于 2012-12-20T10:13:47.847 回答
3
> setkey(input, "id")
> input[ , list(sum(value)), by=id]
   id V1
1:  1  6
2:  2 15
3:  3 34

> input[ variable %in% c("x", "y"), list(sum(value)), by=id]
   id V1
1:  1  6
2:  2 15
3:  3 24

最后一个:

> input[ variable %in% c("x", "y"), list(sum(value)), by=list(id, variable)]
   id variable V1
1:  1        x  1
2:  1        y  5
3:  2        x  4
4:  2        y 11
5:  3        x 15
6:  3        y  9
于 2012-12-20T09:17:42.863 回答
2

我不确定这是否是最好的方法,但您可以尝试:

input[, list(x = sum(value[variable == "x"]), 
             y = sum(value[variable == "y"])), by = "id"]
#    id  x  y
# 1:  1  1  5
# 2:  2  4 11
# 3:  3 15  9
于 2012-12-20T09:34:03.390 回答