我尝试从另一个具有最小值的data.frame中获取数据。
有两种数据集,分别是card和log。
卡
# id BSTN ASTN BSEC ASEC
# 201557 151 150 60633 61302
# 201558 151 150 60159 60680
# 201559 151 150 44757 45149
# 201560 151 150 77551 77923
# 201561 151 150 61160 61606
日志
TRNID ASTN TIME
# 1 150 45140
# 2 150 61300
# 3 150 61600
# 4 150 68570
# 5 150 77900
# 6 150 79125
# 7 150 82477
# 8 150 82767
我想要的是通过以下函数log [log.TRNID和log $ TIMElog $ TIME数据到卡数据中[log.min(card $ ASEC-log $ TIME)]
使用for循环,因为它逐行计算,所以花费的时间太长。有没有for循环的计算吗?
data.frame的最终结果如下:
# id BSTN ASTN BSEC ASEC TRNID TIME
# 201557 151 150 60633 61302 2 61300
# 201558 151 150 60159 60680 2 61300
# 201559 151 150 44757 45149 1 45140
# 201560 151 150 77551 77923 5 77900
# 201561 151 150 61160 61606 3 61600
答案 0 :(得分:2)
另一种方法是滚动联接:
library(data.table)
setDT(log)
setDT(card)
log[, ASEC := TIME]
res <- log[card, roll = -Inf, on = .(ASTN, ASEC)]
# >res
#
# TRNID ASTN TIME ASEC id BSTN BSEC
# 1: 2 150 61350 61302 201557 151 60633
# 2: 2 150 61350 60680 201558 151 60159
# 3: 1 150 46140 45149 201559 151 44757
# 4: 5 150 77950 77923 201560 151 77551
# 5: 3 150 61650 61606 201561 151 61160
滚动连接将在log
中为最后一个连接列(ASEC
)的每个值在card
中找到一个间隔。 -Inf
表示log
的下一个观察值将用于匹配card
中的值。
答案 1 :(得分:1)
使用基数R的一种方法是,对于每个ASEC
,我们在TIME
中找到最小值log
条目的索引,然后使用该索引返回相应的TRNID
并TIME
值并将其添加到card
的原始数据帧中。
card[c("TRNID", "TIME")] <- do.call("rbind", lapply(card$ASEC, function(x) {
inds <- log$TIME - x
idx <- which(inds %in% max(inds[inds < 0]))
c(log$TRNID[idx], log$TIME[idx])
}))
card
# id BSTN ASTN BSEC ASEC TRNID TIME
#1 201557 151 150 60633 61302 2 61300
#2 201558 151 150 60159 60680 1 45140
#3 201559 151 150 44757 45149 1 45140
#4 201560 151 150 77551 77923 5 77900
#5 201561 151 150 61160 61606 3 61600
答案 2 :(得分:1)
由于您需要比较所有card$ASEC
和log$TIME
之间的(绝对值)差异,因此我认为outer
调用在这里最有用:
outer(card$ASEC, log$TIME, `-`)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
# [1,] 15162 -48 -348 -7268 -16648 -17823 -21175 -21465
# [2,] 14540 -670 -970 -7890 -17270 -18445 -21797 -22087
# [3,] -991 -16201 -16501 -23421 -32801 -33976 -37328 -37618
# [4,] 31783 16573 16273 9353 -27 -1202 -4554 -4844
# [5,] 15466 256 -44 -6964 -16344 -17519 -20871 -21161
我们可以快速减少(每行)该值,以找到最小绝对值:
( ind <- apply(abs(outer(card$ASEC, log$TIME, `-`)), 1, which.min) )
# [1] 2 2 1 5 3
cbind.data.frame(card, log[ind,], stringsAsFactors=FALSE)
# id BSTN ASTN BSEC ASEC TRNID ASTN TIME
# 2 201557 151 150 60633 61302 2 150 61350
# 2.1 201558 151 150 60159 60680 2 150 61350
# 1 201559 151 150 44757 45149 1 150 46140
# 5 201560 151 150 77551 77923 5 150 77950
# 3 201561 151 150 61160 61606 3 150 61650