在条件下将which.min应用于data.table

bjh*_*end 2 r data.table

我有一个data.table并且需要知道在给定条件下包含最小值的行的索引.简单的例子:

dt <- data.table(i=11:13, val=21:23)

#     i  val
# 1: 11   21
# 2: 12   22
# 3: 13   23
Run Code Online (Sandbox Code Playgroud)

现在,假设我想知道在这种情况val下哪一行是最小的i>=12,在这种情况下是2.

什么行不通:

dt[i>=12, which.min(val)]
# [1] 1
Run Code Online (Sandbox Code Playgroud)

返回1,因为dt[i>=12]它是第一行.

dt[i>=12, .I[which.min(val)]]
# [1] 1
Run Code Online (Sandbox Code Playgroud)

返回1,因为.I只应该用于分组.

做了什么工作:

为了.I正确应用,我添加了一个分组列:

dt[i>=12, g:=TRUE]
dt[i>=12, .I[which.min(val)], by=g][, V1]
# [1] 2
Run Code Online (Sandbox Code Playgroud)

请注意,这gNAi<12,从而which.min排除从结果组.

但是,这需要额外的计算能力来添加列并执行分组.我的生产data.table有几百万行,我必须经常找到最小值,所以我想避免任何额外的计算.

你有什么想法,如何有效地解决这个问题?

Fra*_*ank 6

但是,这需要额外的计算能力来添加列并执行分组.

因此,如果数据如此重要,请保持数据排序:

setorder(dt, val)
dt[.(i_min = 12), on=.(i >= i_min), mult="first", which = TRUE]
# 2
Run Code Online (Sandbox Code Playgroud)

这也可以扩展到检查更多阈i值.只需给出一个向量i_min =:

dt[.(i_min = 9:14), on=.(i >= i_min), mult="first", which = TRUE]
# [1]  1  1  1  2  3 NA
Run Code Online (Sandbox Code Playgroud)

这个怎么运作

x[i, on=, ...] 是连接的语法.

  • i 可以是另一个表或等效的等长向量列表.
  • .()是一个简写list().
  • on= 可能会出现"非平等联盟"的不平等.
  • mult=可以确定当一行i有多个匹配时会发生什么x.
  • which=TRUE将返回行号x而不是完整的连接表.