我有两个看起来像这样的数据框:
A:
start end X
100 200 1
400 550 1
780 900 1
...
B:
time X
100 0
150 0
200 0
220 0
250 0
300 0
...
对于AI中的每一行,现在要检查数据帧B中的time
是否在数据帧A中的start
和end
之间,如果是,我想更改{{1 }}在B中。因此结果应如下所示:
X
我尝试使用B:
time X
100 1
150 1
200 1
220 0
250 0
300 0
...
在for循环中执行此操作,但是由于我的数据帧很大,因此速度太慢了。有一个智能的R函数可以实现这一目标吗?
答案 0 :(得分:3)
使用data.table
连接语法:
library(data.table)
setDT(A)
setDT(B)
B[A, on = .(time >= start, time <= end), X := i.X]
答案 1 :(得分:2)
data.table::foverlaps
有效地进行基于范围的联接。为了使其正常工作,两个框架都必须具有开始和结束列,这意味着我们需要重复B$time
(建议缩短此过程,但尚未实现)。
library(data.table)
setDT(A)
setDT(B)
B[, time2 := time]
foverlaps(B, A)
# start end X time i.X time2
# 1: 100 200 1 100 0 100
# 2: 100 200 1 150 0 150
# 3: 100 200 1 200 0 200
# 4: NA NA NA 220 0 220
# 5: NA NA NA 250 0 250
# 6: NA NA NA 300 0 300
表面上,这是开始。请注意,仅当X
为i.X
时,我们才想保留B
列并引入X
(最初来自NA
)。我们也不需要保留所有多余的字段,因此我将在同一步骤中修剪掉多余的字段:
foverlaps(B, A)[, X := ifelse(is.na(X), i.X, X)][, .(time, X)]
# time X
# 1: 100 1
# 2: 150 1
# 3: 200 1
# 4: 220 0
# 5: 250 0
# 6: 300 0
还有其他方法可以完成此操作,其中很多(大多数?)都涉及笛卡尔联接,如果两者中都有很多行,伸缩性将很差。