我正在研究财务数据集的一些摘要,我想对某个标准进行排序,但不会丢失连续的剩余汇总值。这是一个简单的例子:
set.seed(1)
tseq <- seq(Sys.time(), length.out = 36, by = "mins")
dt <- data.table(TM_STMP = tseq, COMP = rep(c(rep("A", 4), rep("B", 4), rep("C", 4)), 3), SEC = rep(letters[1:12],3), VOL = rpois(36, 3e+6))
dt2 <- dt[, list(SUM = sum(VOL), MEAN = mean(VOL)), by = list(COMP, SEC)]
dt2
COMP SEC SUM MEAN
1: A a 9000329 3000110
2: A b 9001274 3000425
3: A c 9003505 3001168
4: A d 9002138 3000713
现在我希望每个COMP的SEC获得最高VOL:
dt3 <- dt2[, list(SUM = max(SUM)), by = list(COMP)]
dt3
COMP SUM
1: A 9003505
2: B 9002888
3: C 9005042
这给了我想要的东西,但我希望将其他值保留在特定行(SEC和MEAN)中,使其看起来像这样(手工制作):
COMP SUM SEC MEAN
1: A 9003505 c 3001168
2: B 9002888 f 3000963
3: C 9005042 k 3001681
我怎样才能做到这一点?
答案 0 :(得分:3)
如果您正在寻找对应于最大SUM的SEC和MEAN:
dt3 <- dt2[, list(SUM = max(SUM),SEC=SEC[which.max(SUM)],MEAN=MEAN[which.max(SUM)]), by = list(COMP)]
> dt3
COMP SUM SEC MEAN
1: A 9003110 a 3001037
2: B 9000814 e 2999612
3: C 9002707 i 2999741
编辑:这会更快:
dt2[dt2[, .I[which.max(SUM)], by = list(COMP)]$V1]
答案 1 :(得分:3)
另一种方法是将{。{1}}的data.table传递给:setkey
,然后使用COMP, SUM
,如下所示:
mult="last"
编辑:回答Simon关于此与@metrics之间速度差异的基准测试':
setkey(dt2, COMP, SUM)
dt2[J(unique(COMP)), mult="last"]
# COMP SEC SUM MEAN
# 1: A c 9002500 3000833
# 2: B g 9003312 3001104
# 3: C i 9000058 3000019
答案 2 :(得分:1)
从您的示例输出中,您不清楚要保留/删除的内容,但您可以在j
<{1}}的{{1}}参数中列出其他列。 >
DT[i, j, ]
答案 3 :(得分:1)
我对@Metrics中两种不同方法的表现非常感兴趣,我在下面将其表示为which.func
,而@Arun表示我将其表示为innate.func
。所以,我用上面问题中给出的例子做了一些基准测试。结果如下:
which.func <- function() {dt3 <- dt2[, list(SUM = max(SUM), SEC=SEC[which.max(SUM)], MENA=MEAN[which.max(SUM)]), by = list(COMP)]}
innate.func <- function() {dt3 <- dt2[J(unique(COMP)), mult = "last"]}
library(rbenchmark)
benchmark(which.func, innate.func, replications = 10e+6)
test replications elapsed relative user.self sys.self
2 innate 10000000 24.689 1.000 24.259 0.425
1 which.func 10000000 32.664 1.323 32.216 0.446
当然,这可能对于who.func有点不公平,因为innate.func
涉及对setkey
的调用,这对于大型样本来说是一个时间消费者。如果我在函数中包含setkey
调用,我会得到以下内容:
innate.func <- function() {setkey(dt2, COMP, SUM); dt3 <- dt2[J(unique(COMP)), mult = "last"]; setkey(dt2, NULL)}
test replications elapsed relative user.self sys.self
2 innate.func 10000000 25.271 1.000 24.834 0.430
1 which.func 10000000 26.476 1.048 26.062 0.397
看来,这两种方法的表现非常相似。 @Arun的方法可能在data.table方面更优雅,并且需要更少的代码。它的缺点可能来自于max
或min
不同的聚合函数,其中@Metrics的方法表现出能够在更一般的环境中应用的特性。
我从两种方法中学习并将它们放入我的工具箱中。
答案 4 :(得分:0)
在我进一步处理这里给出的解决方案的过程中,我在上面的问题中遇到了另一个问题,我找到了一个解决方案,我想分享。
如果我想为用户提供选择
aggregate
和aggregate
方法的标准(摘要变量),由crit
表示,然后我遇到了问题,我必须检查,剩下哪些列(参见例如使用哪个列的@Metrics答案)。一个简单的例子:
我们从上面的问题中获取data.table dt2
。现在,用户希望在aggregate = "max"
的data.table摘要中对crit = "SUM"
变量应用dt2
方法。这是一个我发现的解决方案,工作正常(任何讨论当然赞赏):
aggregate = "max"
crit = "SUM"
user call <- expression(do.call(aggregate, list(get(crit))))
dt2[, .SD[which(get(crit) == eval(mycall))], by = COMP]
dt2
COMP SEC SUM MEAN
1: A c 9002500 3000833
2: B g 9003312 3001104
3: C i 9000058 3000019