vry*_*ryb 4 r distance data.table
假设我有以下数据:
d = data.table( id = 1, x = c(1, 10, 17, 35, 37, 45) )
Run Code Online (Sandbox Code Playgroud)
我想看看x by group id中的每个第i个元素是否有一个比它大30到40之间的元素.因此,对于x中第一个元素组ID(1),我希望看到1之后x中的任何值是否在值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 ) )
Run Code Online (Sandbox Code Playgroud)
我和一位同事已经考虑过这个问题了一段时间,我们真的试图避免在这里使用循环,但无法弄明白.这可能没有循环吗?
我最好的尝试是这样的:
d[, valid_gap := any(between( rdist(x[ .N - .I ])[,1], left = 30, right = 40 )), by = id]
Run Code Online (Sandbox Code Playgroud)
但我正在考虑问题,因为试图通过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
Run Code Online (Sandbox Code Playgroud)
先感谢您!
我猜一个非equi连接应该比一个循环更快:
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
Run Code Online (Sandbox Code Playgroud)
对于每一行,我们......
.N); 然后第一步可能会略微加快mult="first".