gpt4 book ai didi

r - 根据条件从大数据表中的每个组中选择一行

转载 作者:行者123 更新时间:2023-12-04 19:04:44 25 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





Subset rows corresponding to max value by group using data.table

(1 个回答)


3年前关闭。




我有一个表,其中键重复了多次,并且使用另一列的最大值为每个键选择一行。

这个例子演示了我目前的解决方案:

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

问题是对于较大的 data.tables 这需要很长时间:
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

我的实际表大约有 1 亿行...

谁能提出更有效的解决方案?

编辑 - 设置键的重要性

建议的解决方案运行良好,但您必须使用 setkey,或订购 DT 才能使其工作:

请参阅代表中没有“每个”的示例:
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 相比,这会更快

 system.time({setkey(DT, X)
DT[DT[,Y==max(Y), by=X]$V1,]})
# user system elapsed
#0.016 0.000 0.016

或者
system.time(DT[DT[, .I[Y==max(Y)], by=X]$V1])
# user system elapsed
# 0.023 0.000 0.023

如果只有两列,
system.time(DT[,list(Y=max(Y)), by=X])
# user system elapsed
# 0.006 0.000 0.007

相比,
system.time(DT[, .SD[Y == max(Y)], by = X] )
# user system elapsed
# 2.946 0.006 2.962

根据@Khashaa、@AnandaMahto 的评论,CRAN 版本 ( 1.9.4 ) 给出了 .SD 的不同结果。与开发版本( 1.9.5 )(我使用的)相比的方法。通过设置 options,您可以获得与“CRAN”版本相同的结果(来自@Arun 的评论)
 options(datatable.auto.index=FALSE)

注意:在“关系”的情况下,此处描述的解决方案将为每个组返回多行(如@docendo discimus 所述)。我的解决方案基于 OP 发布的“代码”。

如果有“关系”,那么你可以使用 uniqueby选项(如果列数为 > 2)
 setkey(DT,X)
unique(DT[DT[,Y==max(Y), by=X]$V1,], by=c("X", "Y"))

微基准
library(microbenchmark)
f1 <- function(){setkey(DT,X)[DT[, Y==max(Y), by=X]$V1,]}
f2 <- function(){DT[DT[, .I[Y==max(Y)], by=X]$V1]}
f3 <- function(){DT[, list(Y=max(Y)), by=X]}
f4 <- function(){DT[, .SD[Y==max(Y)], by=X]}
microbenchmark(f1(), f2(), f3(), f4(), unit='relative', times=20L)
#Unit: relative
# expr min lq mean median uq max neval
# f1() 2.794435 2.733706 3.024097 2.756398 2.832654 6.697893 20
# f2() 4.302534 4.291715 4.535051 4.271834 4.342437 8.114811 20
# f3() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 20
# f4() 533.119480 522.069189 504.739719 507.494095 493.641512 466.862691 20
# cld
# a
# a
# a
# b

数据
N = 10000
k = 25
set.seed(25)
DT = data.table(X = rep(1:N, each = k), Y = rnorm(k*N))

关于r - 根据条件从大数据表中的每个组中选择一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27862958/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com