【问题标题】:Subset rows corresponding to max value by group using data.table使用data.table按组对应于最大值的子集行
【发布时间】:2023-03-30 12:29:01
【问题描述】:

假设我有一个包含一些棒球运动员的data.table

library(plyr)
library(data.table)

bdt <- as.data.table(baseball)

对于每个组(由玩家“id”给出),我想选择与最大游戏数“g”相对应的行。这在plyr 中很简单:

ddply(baseball, "id", subset, g == max(g))

data.table 的等效代码是什么?

我试过了:

setkey(bdt, "id") 
bdt[g == max(g)]  # only one row
bdt[g == max(g), by = id]  # Error: 'by' or 'keyby' is supplied but not j
bdt[, .SD[g == max(g)]] # only one row

这行得通:

bdt[, .SD[g == max(g)], by = id] 

但它只比 plyr 快 30%,这表明它可能不是惯用的。

【问题讨论】:

  • 哇,这很慢,但是如果您使用“year”代替“.SD”...我将获得 0.01、1.58、2.39 一年的用户时间,.SD,plyr ,分别。
  • @Frank 但我想要整个数据框,而不仅仅是年份。我会澄清这个问题。

标签: r data.table greatest-n-per-group


【解决方案1】:

这是data.table 的快速方式:

bdt[bdt[, .I[g == max(g)], by = id]$V1]

这避免了构造 .SD,这是您表达式中的瓶颈。

编辑: 实际上,OP 运行缓慢的主要原因不仅在于它包含 .SD,还在于它以特定方式使用它——通过调用 [.data.table ,目前有很大的开销,因此在循环中运行它(当一个人执行by时)会累积非常大的惩罚。

【讨论】:

  • +1 我敢打赌,Hadley 想以某种编程方式执行此操作,在这种情况下,他会想使用这种语法,bdt[bdt[, .I[g == max(g)], by = id][,V1]] 对吗?
  • @joran 我正在手动构建调用,所以这并不重要
  • 最终将优化原始方法。请参阅FR 2330 优化.SD[i] 查询以保持优雅但使其更快不变。
  • 该问题链接已从 R-Forge 移至 GitHub #613
  • 如果我将verbose = TRUE 添加到内部框架,我会看到GForce FALSE,但它仍然比bdt[bdt[, .(g=max(g)), by=id], on=c("id","g")] 快,尽管我不知道是否总是这样。
猜你喜欢
  • 2021-06-30
  • 2017-12-23
  • 2016-01-07
  • 1970-01-01
  • 2016-06-15
  • 1970-01-01
  • 2019-08-30
  • 1970-01-01
相关资源
最近更新 更多