如何基于R中的另一个数据帧更改数据帧中的值?

时间:2019-10-22 15:56:25

标签: r dataframe mutate

我有两个看起来像这样的数据框:

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中的startend之间,如果是,我想更改{{1 }}在B中。因此结果应如下所示:

X

我尝试使用B: time X 100 1 150 1 200 1 220 0 250 0 300 0 ... 在for循环中执行此操作,但是由于我的数据帧很大,因此速度太慢了。有一个智能的R函数可以实现这一目标吗?

2 个答案:

答案 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

表面上,这是开始。请注意,仅当Xi.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

还有其他方法可以完成此操作,其中很多(大多数?)都涉及笛卡尔联接,如果两者中都有很多行,伸缩性将很差。