我有一个表格,其中键被重复多次,现在需要选择每个键的一行数据,选择时需要使用另外一列中最大值。以下是目前的解决方案示例:
N = 10
k = 2
DT = data.table(X = rep(1:N, each = k), Y = rnorm(k*N))
X Y
1: 1 -1.37925206
2: 1 -0.53837461
3: 2 0.26516340
4: 2 -0.04643483
5: 3 0.40331424
6: 3 0.28667275
7: 4 -0.30342327
8: 4 -2.13143267
9: 5 2.11178673
10: 5 -0.98047230
11: 6 -0.27230783
12: 6 -0.79540934
13: 7 1.54264549
14: 7 0.40079650
15: 8 -0.98474297
16: 8 0.73179201
17: 9 -0.34590491
18: 9 -0.55897393
19: 10 0.97523187
20: 10 1.16924293
> DT[, .SD[Y == max(Y)], by = X]
X Y
1: 1 -0.5383746
2: 2 0.2651634
3: 3 0.4033142
4: 4 -0.3034233
5: 5 2.1117867
6: 6 -0.2723078
7: 7 1.5426455
8: 8 0.7317920
9: 9 -0.3459049
10: 10 1.1692429
问题在于对于较大的数据表,这需要很长时间:
N = 10000
k = 25
DT = data.table(X = rep(1:N, each = k), Y = rnorm(k*N))
system.time(DT[, .SD[Y == max(Y)], by = X])
user system elapsed
9.69 0.00 9.69
我的实际表格有一亿行...
有人能提供更高效的解决方案吗?
编辑 - set key 的重要性
所提出的解决方案很好,但必须使用 setkey 或使 DT 有序才能正常工作:
查看 rep 中未使用 "each" 的示例:
N = 10
k = 2
DT = data.table(X = rep(1:N, k), Y = rnorm(k*N))
DT[DT[, Y == max(Y), by = X]$V1,]
X Y
1: 1 1.26925708
2: 4 -0.66625732
3: 5 0.41498548
4: 8 0.03531185
5: 9 0.30608380
6: 1 0.50308578
7: 4 0.19848227
8: 6 0.86458423
9: 8 0.69825500
10: 10 -0.38160503
.SD[..]
为每个组调用[.data.table
。我们已经意识到这一点,很可能会在1.9.8中进行优化。有一些解决方案可以绕过这个问题(通常使用.I
),你可以通过搜索找到。我会在优化后更新这篇文章。 - Arunoptions(datatable.auto.index=FALSE)
,这样就可以正常工作了。这是新功能中的一个错误,在1.9.5版本中已经修复。 - Arununique(setorder(DT, -Y), by = X)
。对于你的大样本数据,在我的笔记本电脑上使用该方法的system.time都为0。它还将确保每个X只返回一行,即使存在并列情况。 - talat