我有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
NA
为i<12
,因此which.min
会从结果中排除该组。
但是,这需要额外的计算能力来添加列并执行分组。我的高效data.table
有几百万行,我必须经常找到最小值,所以我想避免任何额外的计算。
您有什么想法,如何有效地解决这个问题?
答案 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=
可以确定当一行i
在x
中有多个匹配时会发生什么。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值中的最小值。