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

时间:2017-07-27 22:21:17

标签: 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

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

什么行不通:

dt[i>=12, which.min(val)]
# [1] 1

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

另外

dt[i>=12, .I[which.min(val)]]
# [1] 1

返回 1 ,因为.I只能用于分组。

做了什么工作:

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

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

请注意,g NAi<12,因此which.min会从结果中排除该组。

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

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

2 个答案:

答案 0 :(得分:6)

  

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

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

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

这也可以扩展为检查更多阈值i值。只需在i_min =中添加一个向量:

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

工作原理

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

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

答案 1 :(得分:1)

您可以使用which.min忽略NA值以及#34;掩盖&#34;您不想考虑的价值观点:

dt[,which.min(ifelse(i>=12, val, NA))]

作为此行为的一个简单示例,which.min(c(NA, 2, 1))返回3,因为第3个元素是所有非NA值中的最小值。