假设我有以下数据:
d = data.table( id = 1, x = c(1, 10, 17, 35, 37, 45) )
我想看看 x by group id 中的每个第 i 个元素是否都有比它大 30 到 40 之间的元素。因此,对于按组 id (1) 划分的 x 中的第一个元素,我希望查看 x 中 1 之后的任何值是否介于值 31 和 41 之间。答案是肯定的,因此我想创建一个列 valid_gap对于第一个元素为 TRUE。最后,我希望得到:
d_final = data.table( id = 1, x = c(1, 10, 17, 35, 37, 45), valid_gap = c(T, T, F, F, F, F ) )
我和一位同事考虑过这个问题一段时间,我们真的很想避免在这里使用循环,但无法弄清楚。这可能没有循环吗?
我最好的尝试是这样的:
d[, valid_gap := any(between( rdist(x[ .N - .I ])[,1], left = 30, right = 40 )), by = id]
但我正在考虑这个问题,因为它试图像在循环中一样对 x 进行索引,我怀疑这是错误的想法。
编辑 - “坏”解决方案:
x = c(1, 10, 17, 35, 37, 45)
valid_gap = c()
for( i in 1:length(x) ) {
if( i == length(x) ){
valid_gap = c(valid_gap, F)
} else {
valid_gap = c(valid_gap, any(between( rdist( x[ x >= x[i] ] )[,1], left = 30, right = 40 )) )
}
}
valid_gap
先感谢您!
最佳答案
我想非等连接应该比循环快:
d[, v :=
d[.(id = id, x0 = x + 30, x1 = x + 40), on=.(id, x >= x0, x <= x1),
.N
, by=.EACHI][, N > 0L]
]
id x v
1: 1 1 TRUE
2: 1 10 TRUE
3: 1 17 FALSE
4: 1 35 FALSE
5: 1 37 FALSE
6: 1 45 FALSE
对于每一行,我们...
.N
);然后 使用
mult="first"
第一步可能会稍微快一点.
关于R data.table 按组从第 i 个元素到每个剩余元素的距离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43106465/