我的问题与groupset的子集有关,data.table但不同.
想象一下这样的数据集:
tmp <- data.table(x = 1:10, y = c(27, 70, 54, 18, 50, 44, 22, 73, 6, 5))
Run Code Online (Sandbox Code Playgroud)
对于数据的每一行,我想计算一个新值z,它是min(y)所有具有较大x值的行.例如,对于x为3的数据的第三行,我想要min(y)x> 3的行(这将是值5).出于我们的意图和目的,您可以假设数据已经按x排序.
起初我想过使用这样的函数:
min.y <- function(val, dt) {
dt[x > val, min(y)]
}
Run Code Online (Sandbox Code Playgroud)
但是调用tmp[, z:= fun(x, tmp)]会产生一条警告信息:
In min(y) : no non-missing arguments to min; returning Inf
Run Code Online (Sandbox Code Playgroud)
这样做的正确方法是什么?
PS:显然,对于最后一行,我希望得到NA作为结果
方法1:
既然你说我们可以假设数据已经排序,x你可以使用从结尾开始的累积最小值y.我们删除了第一个观察,以便我们进行>搜索而不是>=:
tmp$min_y <- c(rev(cummin(rev(tmp$y[-1]))), NA)
Run Code Online (Sandbox Code Playgroud)
更新:旧方法有效地进行了>=搜索,而不是>.更新了>.
方法2:Data.table
如果您想使用data.table,可以尝试按行分组,然后在其中进行分组J.ifelse是必需的,所以当我们在最后一行时,我们不采取没有值的min:
tmp[, "min_y" := {curr_x <- x
tmp_subs <- tmp[x > curr_x]
ifelse(nrow(tmp_subs)>0, min(tmp[x > curr_x][["y"]]), NA_real_)},
by = 1:nrow(tmp)]
tmp
# x y min_y
# 1: 1 27 5
# 2: 2 70 5
# 3: 3 54 5
# 4: 4 18 5
# 5: 5 50 5
# 6: 6 44 5
# 7: 7 22 5
# 8: 8 73 5
# 9: 9 6 5
#10: 10 5 NA
Run Code Online (Sandbox Code Playgroud)
因为5最终的价值是最终的一切5.让我们更有趣一点:
tmp <- data.table(x = 1:10, y = c(27, 70, 54, 18, 50, 44, 22, 73, 47, 58))
Run Code Online (Sandbox Code Playgroud)
我们的结果将是:
# x y min_y
# 1: 1 27 18
# 2: 2 70 18
# 3: 3 54 18
# 4: 4 18 22
# 5: 5 50 22
# 6: 6 44 22
# 7: 7 22 47
# 8: 8 73 47
# 9: 9 47 58
#10: 10 58 NA
Run Code Online (Sandbox Code Playgroud)