我正在寻找操纵data.table
对象的模式,这些对象的结构类似于melt
包中使用reshape2
创建的数据帧的结构。我正在处理数百万行的数据表。绩效至关重要。
问题的一般形式是,是否有一种方法可以根据列中值的子集执行分组,并使分组操作的结果创建一个或多个新列。
问题的一个特定形式可能是如何使用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
答案 0 :(得分:9)
快速未经测试的答案:似乎您正在寻找 by-without-by ,a.k.a。 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"),with=FALSE], 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-by-by与by组合,如上所述,则by-without-by然后就像子集一样运行;即,j
仅在缺少by时i
的每一行运行(因此名称 by-without-by )。因此,您需要再次在variable
中添加by
,如上所示。
或者,以下内容应由id
分组而不是“x”和“y”的并集(但上面是您在问题中要求的内容,iiuc):
input[c("x","y"),sum(value),by=id]
答案 1 :(得分: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
答案 2 :(得分: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